home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / fsmake / fsmake.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-05  |  74.5 KB  |  2,475 lines

  1. /* 
  2.  * fsmake.c --
  3.  *
  4.  *    Format a domain to be an empty domain.
  5.  *
  6.  * Copyright (C) 1986 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/admin/fsmake/RCS/fsmake.c,v 1.18 90/11/01 23:24:48 jhh Exp $ SPRITE (Berkeley)";
  12. #endif
  13.  
  14. #include "fsmake.h"
  15. #include <assert.h>
  16.  
  17. /*
  18.  * Constants settable via the command line.
  19.  */
  20. static int kbytesToFileDesc = 4;/* The ratio of kbytes to
  21.                  * the number of file descriptors */
  22. Boolean printOnly = TRUE;       /* Stop after computing the domain header
  23.                  * and just print it out. No disk writes */
  24. static Boolean overlapBlocks = FALSE;
  25.                                 /* Allow filesystem blocks to overlap track
  26.                  * boundaries.  Some disk systems can't deal. */
  27. static Boolean scsiDisk = TRUE;    /* If TRUE then simpler geometry is computed
  28.                  * that knows that SCSI controllers don't
  29.                  * think in terms of cylinders, heads, and
  30.                  * sectors.  Instead, they think in terms of
  31.                  * logical sector numbers, so we punt on finding
  32.                  * rotationally optimal block positions. */
  33. static int bootSectors = -1;    /* Number of boot sectors. */
  34. static int hostID = 0;        /* Host id to write into domain header. 
  35.                  * A host id of 0 means use local host id. */
  36. static Boolean repartition = FALSE;
  37.                                 /* If TRUE then the partition map is changed. */
  38. static Boolean reconfig = FALSE;    /* If TRUE then the disk configuration
  39.                  * is changed. */
  40. static Boolean partdisktab = FALSE;
  41.                                 /* If TRUE then read the partition map from
  42.                  * the disktab file. */
  43. static Boolean configdisktab = FALSE;
  44.                                 /* If TRUE then read the config information
  45.                  * from the disktab file, otherwise get the
  46.                  * disk size information directly from the
  47.                  * disk and compute the "best" configuration..*/
  48. static char *disktabName = "/etc/disktab"; /* Name of disktab file. */
  49. static char *sizeString = NULL;    /* Size of partitions. */
  50. static char *diskType = NULL;    /* Type of disk (e.g.rz55). */
  51. static char *labelTypeName = NULL; /* Type of label (e.g. sun). */
  52. static char *dirName = NULL;    /* Name of directory that contains files to
  53.                  * copy to the disk. */
  54. extern char *hostFileName;      /* Name of file to get host info from.  By
  55.                                    default it is /etc/spritehosts.  It is 
  56.                    defined in Host_Start.c. */
  57.  
  58. /*
  59.  * The following are used to go from a command line like
  60.  * makeFilesystem -D rsd0 -P b
  61.  * to /dev/rsd0a     - for the partition that has the disk label
  62.  * and to /dev/rsd0b    - for the partition to format.
  63.  */
  64. static char *deviceName;    /* Set to "rsd0" or "rxy1", etc. */
  65. static char *partName;        /* Set to "a", "b", "c" ... "g" */
  66. static char *rawDeviceName;    /* Set to "raw_rsd00", etc */
  67. static char defaultFirstPartName[] = "a";
  68. static char *firstPartName = defaultFirstPartName;
  69. static char defaultDevDirectory[] = "/dev";
  70. static char *devDirectory = defaultDevDirectory;
  71.  
  72. static char *hostIDString = NULL;
  73.  
  74. static Option optionArray[] = {
  75.     {OPT_STRING, "dev", (Address)&deviceName,
  76.     "Required: Name of device, eg \"rsd0\" or \"rxy1\""},
  77.     {OPT_STRING, "part", (Address)&partName,
  78.     "Required: Partition ID: (a, b, c, d, e, f, g)"},
  79.     {OPT_STRING, "rawdev", (Address)&rawDeviceName,
  80.     "Required: Name of raw device, eg \"raw_rsd00\""},
  81.     {OPT_TRUE, "scsi", (Address)&scsiDisk,
  82.     "Compute geometry for SCSI type disk (TRUE)"},
  83.     {OPT_FALSE, "noscsi", (Address)&scsiDisk,
  84.     "Compute geometry for non-SCSI disk (FALSE)"},
  85.     {OPT_TRUE, "overlap", (Address)&overlapBlocks,
  86.     "Overlap filesystem blocks across track boundaries (FALSE)"},
  87.     {OPT_INT, "ratio", (Address)&kbytesToFileDesc,
  88.     "Ratio of Kbytes to file descriptors (4)"},
  89.     {OPT_TRUE, "test", (Address)&printOnly,
  90.     "Test: print results, don't write disk (TRUE)"},
  91.     {OPT_FALSE, "write", (Address)&printOnly,
  92.     "Write the disk (FALSE)"},
  93.     {OPT_STRING, "devDir", (Address)&devDirectory,
  94.     "Name of device directory (\"/dev\")"},
  95.     {OPT_STRING, "initialPart", (Address)&firstPartName,
  96.     "Name of initial partition (\"a\")"},
  97.     {OPT_INT, "boot", (Address)&bootSectors,
  98.     "Number of boot sectors in root partition"},
  99.     {OPT_STRING, "host", (Address)&hostIDString,
  100.     "Host id or name of machine domain is attached to."},
  101.     {OPT_TRUE, "repartition", (Address)&repartition,
  102.     "Change the partitioning of the disk.  USE ONLY ON EMPTY DISKS"},
  103.     {OPT_TRUE, "reconfig", (Address) &reconfig,
  104.     "Change the disk configuration info in label. USE ONLY ON EMPTY DISKS"},
  105.     {OPT_TRUE, "configdisktab", (Address)&configdisktab,
  106.     "Reconfigure according to info in disktab file"},
  107.     {OPT_TRUE, "partdisktab", (Address)&partdisktab,
  108.     "Repartition according to info in disktab file"},
  109.     {OPT_STRING, "disktabName", (Address)&disktabName,
  110.     "Name of the disktab file"},
  111.     {OPT_STRING, "sizes", (Address)&sizeString,
  112.     "Size of partitions (as a percentage), eg \"a:25,g:75\""},
  113.     {OPT_STRING, "disktype", (Address)&diskType,
  114.     "Type of disk. Used to look up information in disktab file"},
  115.     {OPT_STRING, "labeltype", (Address)&labelTypeName,
  116.     "Type of native disk label (sun or dec)"},
  117.     {OPT_STRING, "dir", (Address)&dirName,
  118.     "Directory to copy files from"},
  119.     {OPT_STRING, "spritehosts", (Address)&hostFileName,
  120.         "File to get host information from"},
  121. };
  122. #define numOptions (sizeof(optionArray) / sizeof(Option))
  123.  
  124. /*
  125.  * Time of day when this program runs.
  126.  */
  127.  
  128. static struct timeval curTime;
  129.  
  130. static int        freeFDNum;    /* The currently free file descriptor.*/
  131. static int        freeBlockNum;    /* The currently free data block. */
  132. static unsigned char    *fdBitmapPtr;    /* Pointer to the file descriptor
  133.                      * bitmap. */
  134. static unsigned char    *cylBitmapPtr;    /* Pointer to the cylinder bit map. */
  135. static int            bytesPerCylinder;/* The number of bytes in
  136.                       * the bitmap for a cylinder.*/
  137. static Ofs_DomainHeader *headerPtr;    /* The domain header. */
  138. static Ofs_SummaryInfo *summaryPtr;    /* The summary info. */
  139.  
  140. static char *myName;
  141. /*
  142.  * Forward Declarations.
  143.  */
  144.  
  145. static void Usage _ARGS_((void));
  146. static ReturnStatus MakeFilesystem _ARGS_((int firstPartFID, int partFID,
  147.     int partition, int spriteID, Disk_Label **labelPtrPtr));
  148. static void CopyTree _ARGS_((int partFID, char *dirName, int dirFDNum,
  149.     Fsdm_FileDescriptor *dirFDPtr, int parentFDNum,
  150.     Boolean createDir, char *path));
  151. static ReturnStatus SetDomainHeader _ARGS_((Disk_Label *labelPtr,
  152.     Ofs_DomainHeader *headerPtr, int spriteID, int partition));
  153. static void SetSCSIDiskGeometry _ARGS_((Disk_Label *labelPtr,
  154.     Ofs_Geometry *geoPtr));
  155. static void SetDiskGeometry _ARGS_((Disk_Label *labelPtr,
  156.     Ofs_Geometry *geoPtr));
  157. static void SetDomainParts _ARGS_((Disk_Label *labelPtr, int partition,
  158.     Ofs_DomainHeader *headerPtr));
  159. static void SetSummaryInfo _ARGS_((Ofs_DomainHeader *headerPtr,
  160.     Ofs_SummaryInfo *summaryPtr));
  161. static ReturnStatus WriteAllFileDescs _ARGS_((int partFID,
  162.     Ofs_DomainHeader *headerPtr));
  163. static char *MakeFileDescBitmap _ARGS_((Ofs_DomainHeader *headerPtr));
  164. static ReturnStatus WriteBitmap _ARGS_((int partFID,
  165.     Ofs_DomainHeader *headerPtr));
  166. static ReturnStatus WriteRootDirectory _ARGS_((int partFID,
  167.     Ofs_DomainHeader *headerPtr, Fsdm_FileDescriptor *fdPtr));
  168. static ReturnStatus WriteLostFoundDirectory _ARGS_((int partFID,
  169.     Ofs_DomainHeader *headerPtr));
  170. static void InitDesc _ARGS_((Fsdm_FileDescriptor *fileDescPtr, int fileType,
  171.     int numBytes, int devServer, int devType, int devUnit,
  172.     int uid, int gid, int permissions, long time));
  173. static ReturnStatus AddToDirectory _ARGS_((int fid,
  174.     Ofs_DomainHeader *headerPtr, Boolean writeDisk, DirIndexInfo *dirIndexPtr,
  175.     Fslcl_DirEntry **dirEntryPtrPtr, int fileNumber, char *fileName));
  176. static ReturnStatus OpenDir _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  177.     Fsdm_FileDescriptor *fdPtr, DirIndexInfo *indexInfoPtr,
  178.     Fslcl_DirEntry **dirEntryPtrPtr));
  179. static ReturnStatus NextDirEntry _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  180.     Boolean writeDisk, DirIndexInfo *indexInfoPtr,
  181.     Fslcl_DirEntry **dirEntryPtrPtr));
  182. static ReturnStatus CloseDir _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  183.     Boolean writeDisk, DirIndexInfo *indexInfoPtr));
  184. static ReturnStatus ReadFileDesc _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  185.     int fdNum, Fsdm_FileDescriptor *fdPtr));
  186. static ReturnStatus WriteFileDesc _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  187.     int fdNum, Fsdm_FileDescriptor *fdPtr));
  188. static void CreateDir _ARGS_((Address blocks, int numBlocks,
  189.     int dot, int dotDot));
  190. static void MarkDataBitmap _ARGS_((Ofs_DomainHeader *headerPtr,
  191.     unsigned char *cylBitmapPtr, int blockNum, int numFrags));
  192. static unsigned char *ReadFileDescBitmap _ARGS_((int fid,
  193.     Ofs_DomainHeader *headerPtr));
  194. static unsigned char *ReadBitmap _ARGS_((int fid,
  195.     Ofs_DomainHeader *headerPtr));
  196. static void WriteFileDescBitmap _ARGS_((int fid, Ofs_DomainHeader *headerPtr,
  197.     unsigned char *bitmap));
  198.  
  199. extern char *getwd();
  200.  
  201.  
  202. /*
  203.  *----------------------------------------------------------------------
  204.  *
  205.  * main --
  206.  *
  207.  *    Create the required file names from the command line
  208.  *    arguments.  Then open the first partition on the disk
  209.  *    because it contains the disk label, and open the partition
  210.  *    that is to be formatted.
  211.  *
  212.  * Results:
  213.  *    None.
  214.  *
  215.  * Side effects:
  216.  *    Calls MakeFilesystem
  217.  *
  218.  *----------------------------------------------------------------------
  219.  */
  220. void
  221. main(argc, argv)
  222.     int argc;
  223.     char *argv[];
  224. {
  225.     ReturnStatus status;    /* status of system calls */
  226.     int firstPartFID;        /* File ID for first parition on the disk */
  227.     int partFID;        /* File ID for partiton to format */
  228.     int rawFID = -1;
  229.     char firstPartitionName[64];
  230.     char partitionName[64];
  231.     int partition;        /* Index of partition derived from the
  232.                  * partition name */
  233.     int spriteID;        /* Host ID of the machine with the disks */
  234.     Fs_Attributes attrs;
  235.     Disk_NativeLabelType    labelType;    
  236.     Disk_Label            *labelPtr = NULL;
  237.     int    sizes[8];
  238.     int i;
  239.  
  240.     myName = argv[0];
  241.     argc = Opt_Parse(argc, argv,optionArray, numOptions, 0);
  242.     if (argc > 1) {
  243.     Usage();
  244.     }
  245.     status = SUCCESS;
  246.     if (deviceName == (char *)0) {
  247.     fprintf(stderr,"Specify device name with -dev option\n");
  248.     status = FAILURE;
  249.     }
  250.     if (partName == (char *)0) {
  251.     fprintf(stderr,"Specify partition with -part option\n");
  252.     status = FAILURE;
  253.     }
  254.     if (bootSectors > FSDM_MAX_BOOT_SECTORS) {
  255.     fprintf(stderr,"Maximum number of boot sectors is %d.\n", 
  256.         FSDM_MAX_BOOT_SECTORS);
  257.     status = FAILURE;
  258.     }
  259.     if ((bootSectors != -1) && (bootSectors % FSDM_BOOT_SECTOR_INC != 0)) {
  260.     fprintf(stderr, "Number of boot sectors must be a multiple of %d.\n",
  261.         FSDM_BOOT_SECTOR_INC);
  262.     status = FAILURE;
  263.     }
  264.     for (i = 0; i < 8; i++) {
  265.     sizes[i] = 0;
  266.     }
  267.     if (sizeString != NULL) {
  268.     char *cPtr;
  269.     int part;
  270.     int size;
  271.     int n;
  272.     cPtr = sizeString;
  273.     while (*cPtr != '\0') {
  274.         part = (int) (*cPtr - 'a');
  275.         if (part < 0 || part > 7) {
  276.         fprintf(stderr, 
  277.         "Argument to -sizes parameter must start with partition.\n");
  278.         Usage();
  279.         }
  280.         cPtr++;
  281.         if (*cPtr != ':') {
  282.         fprintf(stderr, 
  283.         "Argument to -sizes parameter is missing a ':'.\n");
  284.         Usage();
  285.         }
  286.         cPtr++;
  287.         n = sscanf(cPtr,"%d",&size);
  288.         if (n != 1) {
  289.         fprintf(stderr, 
  290.     "Argument to -sizes parameter must have an integer following the ':'\n");
  291.         Usage();
  292.         }
  293.         sizes[part] = size;
  294.         cPtr = strchr(cPtr, ',');
  295.         if (cPtr == NULL) {
  296.         break;
  297.         }
  298.         cPtr++;
  299.     }
  300.     }
  301.     if (hostIDString != (char *) NULL) {
  302.     int        scanned;
  303.     int        temp;
  304.     Host_Entry    *entryPtr;
  305.  
  306.     scanned = sscanf(hostIDString, " %d", &temp);
  307.     if (scanned == 1) {
  308.         entryPtr = Host_ByID(temp);
  309.         if (entryPtr == NULL) {
  310.         fprintf(stderr, 
  311.             "WARNING: Host %d is not in /etc/spritehosts.\n", temp);
  312.         }
  313.         hostID = temp;
  314.     } else {
  315.         entryPtr = Host_ByName(hostIDString);
  316.         if (entryPtr == NULL) {
  317.         fprintf(stderr, 
  318.             "Host %s is not in /etc/spritehosts.\n", temp);
  319.         status = FAILURE;
  320.         }
  321.         hostID = entryPtr->id;
  322.     }
  323.     }
  324.     labelType = DISK_NO_LABEL;
  325.     if (labelTypeName != NULL) {
  326.     if (!strcasecmp(labelTypeName, "sun")) {
  327.         labelType = DISK_SUN_LABEL;
  328.     } else if (!strcasecmp(labelTypeName, "dec")) {
  329.         labelType = DISK_DEC_LABEL;
  330.     } else {
  331.         fprintf(stderr, 
  332.         "Argument to -labeltype must be \"sun\" or \"dec\"\n");
  333.         status = FAILURE;
  334.     }
  335.     }
  336.     if (status != SUCCESS) {
  337.     exit(status);
  338.     }
  339.     /*
  340.      * Gen up the name of the first partition on the disk,
  341.      * and the name of the parition that needs to be formatted.
  342.      */
  343.     sprintf(firstPartitionName, "%s/%s%c", devDirectory, deviceName,
  344.     *firstPartName);
  345.     sprintf(partitionName, "%s/%s%c", devDirectory, deviceName,
  346.     *partName);
  347.     if (rawDeviceName != NULL) {
  348.     char buffer[64];
  349.     sprintf(buffer, "%s/%s", devDirectory, rawDeviceName);
  350.     if (!printOnly) {
  351.         rawFID = open(buffer, O_RDWR);
  352.     } else {
  353.         rawFID = open(buffer, O_RDONLY);
  354.     }
  355.     if (rawFID < 0) {
  356.         fprintf(stderr, "Can't open raw device %s: ", buffer);
  357.         perror((char *) NULL);
  358.         exit(FAILURE);
  359.     }
  360.     }
  361.     if (reconfig) {
  362.     if (rawFID < 0) {
  363.         fprintf(stderr, 
  364.     "You must specify a raw device with the -reconfig flag\n");
  365.         exit(FAILURE);
  366.     }
  367.     status = Reconfig(rawFID, configdisktab, disktabName, diskType,
  368.         labelType, scsiDisk, &labelPtr);
  369.     if (status != SUCCESS) {
  370.         fprintf(stderr, "Reconfiguration of disk failed.\n");
  371.         exit(1);
  372.     }
  373.     }
  374.     if (repartition || reconfig) {
  375.     if (rawFID < 0) {
  376.         fprintf(stderr, 
  377.     "You must specify a raw device with the -repartition flag\n");
  378.         exit(FAILURE);
  379.     }
  380.     status = Repartition(rawFID, partdisktab, disktabName, diskType,
  381.         labelType, partition,
  382.         sizes, &labelPtr);
  383.     if (status != SUCCESS) {
  384.         fprintf(stderr, "Repartition of disk failed.\n");
  385.         exit(1);
  386.     }
  387.     printf("New disk label:\n");
  388.     bzero(labelPtr->asciiLabel,sizeof(labelPtr->asciiLabel));
  389.     strcpy(labelPtr->asciiLabel,diskType);
  390.     Disk_PrintLabel(labelPtr);
  391.     status = ConfirmDiskSize(rawFID, labelPtr, sizes);
  392.     if (status != SUCCESS) {
  393.         exit(status);
  394.     }
  395.     if (!printOnly) {
  396.         status = Disk_WriteLabel(rawFID, labelPtr);
  397.         if (status != SUCCESS) {
  398.         fprintf(stderr, "Can't write label to raw device\n");
  399.         exit(status);
  400.         }
  401.     }
  402.     }
  403.     if (!printOnly) {
  404.     firstPartFID = open(firstPartitionName, O_RDWR);
  405.     } else {
  406.     firstPartFID = open(firstPartitionName, O_RDONLY);
  407.     }
  408.     if (firstPartFID < 0 ) {
  409.     fprintf(stderr, "Can't open first partition %s: ", firstPartitionName);
  410.     perror((char *) NULL);
  411.     exit(FAILURE);
  412.     }
  413.     if (!printOnly) {
  414.     partFID = open(partitionName, O_RDWR);
  415.     } else {
  416.     partFID = open(partitionName, O_RDONLY);
  417.     }
  418.     if (partFID < 0) {
  419.     perror("Can't open partition to format");
  420.     exit(FAILURE);
  421.     }
  422.  
  423.     partition = partName[0] - 'a';
  424.     if (partition < 0 || partition > 7) {
  425.     fprintf(stderr,
  426.            "Can't determine partition index from the partition name\n");
  427.     exit(FAILURE);
  428.     }
  429. #ifdef sprite  /* This stuff will not work if run under Unix. */
  430.     if (hostID == 0) {
  431.  
  432.     /*
  433.      * Determine where the disk is located so we can set the
  434.      * spriteID in the header correctly.
  435.      */
  436.     Fs_GetAttributesID(firstPartFID, &attrs);
  437.     if (attrs.devServerID == FS_LOCALHOST_ID) {
  438.         Proc_GetHostIDs((int *) NULL, &spriteID);
  439.         printf("Making filesystem for local host, ID = 0x%x\n", spriteID);
  440.     } else {
  441.         spriteID = attrs.devServerID;
  442.         printf("Making filesystem for remote host 0x%x\n", spriteID);
  443.     }
  444.     } else
  445. #endif
  446.     {
  447.     spriteID = hostID;
  448.     printf("Making filesystem for host, ID = 0x%x\n", spriteID);
  449.     }
  450.     gettimeofday(&curTime, (struct timezone *) NULL);
  451.     printf("MakeFilesystem based on 4K filesystem blocks\n");
  452.     status = MakeFilesystem(firstPartFID, partFID, partition, spriteID, 
  453.     &labelPtr);
  454.     if ((status == SUCCESS) && (dirName != NULL)) {
  455.     Fsdm_FileDescriptor    rootDesc;
  456.     printf("Copying %s to new filesystem.\n", dirName);
  457.     fdBitmapPtr = ReadFileDescBitmap(partFID, headerPtr);
  458.     cylBitmapPtr = ReadBitmap(partFID, headerPtr);
  459.     ReadFileDesc(partFID, headerPtr, FSDM_ROOT_FILE_NUMBER, &rootDesc);
  460.     CopyTree(partFID, dirName, FSDM_ROOT_FILE_NUMBER, &rootDesc,
  461.         FSDM_ROOT_FILE_NUMBER, FALSE, "/");
  462.     WriteFileDesc(partFID, headerPtr, FSDM_ROOT_FILE_NUMBER, &rootDesc);
  463.     if (!printOnly) {
  464.         status = Disk_WriteSummaryInfo(partFID, labelPtr, summaryPtr);
  465.         if (status != 0) {
  466.         perror("Summary sector write failed (2)");
  467.         exit(status);
  468.         }
  469.         WriteFileDescBitmap(partFID, headerPtr, fdBitmapPtr);
  470.         WriteBitmap(partFID, headerPtr);
  471.     }
  472.     }
  473.     fflush(stderr);
  474.     fflush(stdout);
  475.     (void)close(firstPartFID);
  476.     (void)close(partFID);
  477.     exit(status);
  478. }
  479.  
  480. /*
  481.  *----------------------------------------------------------------------
  482.  *
  483.  * Usage --
  484.  *
  485.  *    Prints out the correct command syntax and exits..
  486.  *
  487.  * Results:
  488.  *    None.
  489.  *
  490.  * Side effects:
  491.  *    The program exits.
  492.  *
  493.  *----------------------------------------------------------------------
  494.  */
  495.  
  496. static void
  497. Usage()
  498. {
  499.     Opt_PrintUsage(myName, optionArray, Opt_Number(optionArray));
  500.     exit(1);
  501. }
  502.  
  503. /*
  504.  *----------------------------------------------------------------------
  505.  *
  506.  * MakeFilesystem --
  507.  *
  508.  *    Format a disk partition, or domain, to be an empty filesystem.
  509.  *
  510.  * Results:
  511.  *    An error code.
  512.  *
  513.  * Side effects:
  514.  *    Write all over the disk partition.
  515.  *
  516.  *----------------------------------------------------------------------
  517.  */
  518. static ReturnStatus
  519. MakeFilesystem(firstPartFID, partFID, partition, spriteID, labelPtrPtr)
  520.     int firstPartFID;    /* Handle on the first partition of the disk */
  521.     int partFID;    /* Handle on the partition of the disk to format */
  522.     int partition;    /* Index of parition that is to be formatted */
  523.     int spriteID;    /* Host ID of the machine with the disks, this
  524.              * gets written on the disk and used at boot time */
  525.     Disk_Label    **labelPtrPtr; /* Ptr to ptr to disk label. */
  526. {
  527.     ReturnStatus     status;
  528.     Ofs_DomainHeader    oldDomainHeader;
  529.     Ofs_SummaryInfo    oldSummaryInfo;
  530.     Fsdm_FileDescriptor rootFD;
  531.     Fsdm_FileDescriptor *rootFDPtr = &rootFD;
  532.     Disk_Label    *labelPtr = *labelPtrPtr;
  533.  
  534.     if (labelPtr == NULL) {
  535.     labelPtr = Disk_ReadLabel(firstPartFID);
  536.     if (labelPtr == NULL) {
  537.         fprintf(stderr, "Unable to read disk label.\n");
  538.         return FAILURE;
  539.     }
  540.     }
  541.     *labelPtrPtr = labelPtr;
  542.     summaryPtr = Disk_ReadSummaryInfo(partFID, labelPtr);
  543.     if (summaryPtr != NULL) {
  544.     if (!printOnly) {
  545.         char answer[10];
  546.  
  547.         printf("\nYou are about to overwrite the \"%s\" filesystem.\n", 
  548.         summaryPtr->domainPrefix);
  549.         printf("Do you really want to do this?[y/n] ");
  550.         if (scanf("%10s",answer) != 1) {
  551.         exit(SUCCESS);
  552.         }
  553.         if ((*answer != 'y') && (*answer != 'Y')) {
  554.         return SUCCESS;
  555.         }
  556.     }
  557.     }
  558.     bzero((char *) &oldDomainHeader, sizeof(oldDomainHeader));
  559.     bzero((char *) &oldSummaryInfo, sizeof(oldSummaryInfo));
  560.     if (!printOnly) {
  561.     status = Disk_WriteDomainHeader(partFID, labelPtr, &oldDomainHeader);
  562.     if (status != SUCCESS) {
  563.         printf("Clear of old domain header failed\n");
  564.     }
  565.     status = Disk_WriteSummaryInfo(partFID, labelPtr, &oldSummaryInfo);
  566.     if (status != SUCCESS) {
  567.         printf("Clear of old summary info failed\n");
  568.     }
  569.     }
  570.     /*
  571.      * The user has specified the number of boot sectors.
  572.      */
  573.     if (bootSectors >= 0) {
  574.     labelPtr->summarySector = bootSectors + 1;
  575.     labelPtr->domainSector = bootSectors + 2;
  576.     labelPtr->numBootSectors = bootSectors;
  577.     } else {
  578.     Disk_Label *newLabelPtr;
  579.     newLabelPtr = Disk_NewLabel(labelPtr->labelType);
  580.     labelPtr->summarySector = newLabelPtr->summarySector;
  581.     labelPtr->domainSector = newLabelPtr->domainSector;
  582.     labelPtr->numBootSectors = newLabelPtr->numBootSectors;
  583.     free((char *) newLabelPtr);
  584.     }
  585.     headerPtr = (Ofs_DomainHeader *) malloc(sizeof(Ofs_DomainHeader));
  586.     status = SetDomainHeader(labelPtr, headerPtr, spriteID, partition);
  587.     if (status != SUCCESS) {
  588.     return FAILURE;
  589.     }
  590.     Disk_PrintDomainHeader(headerPtr);
  591.  
  592.     if (!printOnly) {
  593.     status = Disk_WriteLabel(partFID, labelPtr);
  594.     if (status != SUCCESS) {
  595.         perror("Disk label write failed"); 
  596.         return(status);
  597.     }
  598.     status = Disk_WriteDomainHeader(partFID, labelPtr, headerPtr);
  599.     if (status != SUCCESS) {
  600.         perror("DomainHeader write failed");
  601.         return(status);
  602.     }
  603.     }
  604.     summaryPtr = (Ofs_SummaryInfo *) malloc(DEV_BYTES_PER_SECTOR);
  605.     SetSummaryInfo(headerPtr, summaryPtr);
  606.     if (!printOnly) {
  607.     status = Disk_WriteSummaryInfo(partFID, labelPtr, summaryPtr);
  608.     if (status != SUCCESS) {
  609.         perror("Summary sector write failed");
  610.         return(status);
  611.     }
  612.     }
  613.     status = WriteAllFileDescs(partFID, headerPtr);
  614.     if (status != SUCCESS) {
  615.     perror("WriteAllFileDescs failed");
  616.     return(status);
  617.     }
  618.     status = WriteBitmap(partFID, headerPtr);
  619.     if (status != SUCCESS) {
  620.     perror("WriteBitmap failed");
  621.     return(status);
  622.     }
  623.     ReadFileDesc(partFID, headerPtr, FSDM_ROOT_FILE_NUMBER, rootFDPtr);
  624.     status = WriteRootDirectory(partFID, headerPtr, rootFDPtr);
  625.     WriteFileDesc(partFID, headerPtr, FSDM_ROOT_FILE_NUMBER, rootFDPtr);
  626.     if (status != SUCCESS) {
  627.     perror("WriteRootDirectory failed");
  628.     return(status);
  629.     }
  630.     status = WriteLostFoundDirectory(partFID, headerPtr);
  631.     if (status != SUCCESS) {
  632.     perror("WriteLostFoundDirectory failed");
  633.     return(status);
  634.     }
  635.     return(SUCCESS);
  636. }
  637.  
  638. /*
  639.  *----------------------------------------------------------------------
  640.  *
  641.  * CopyTree --
  642.  *
  643.  *    Copy the tree of files in the given directory
  644.  *    the disk table.
  645.  *
  646.  * Results:
  647.  *    A pointer to a disk info struct.
  648.  *
  649.  * Side effects:
  650.  *    Disk info struct malloc'd and initialized.  The disk header will be
  651.  *    written if is successfully set up.
  652.  *
  653.  *----------------------------------------------------------------------
  654.  */
  655. static void
  656. CopyTree(partFID, dirName, dirFDNum, dirFDPtr, parentFDNum, createDir, path)
  657.     int            partFID;    /* Handle on raw disk. */
  658.     char        *dirName;    /* Name of directory to copy. */
  659.     int            dirFDNum;    /* File number of directory. */
  660.     Fsdm_FileDescriptor    *dirFDPtr;    /* File descriptor of directory. */
  661.     int            parentFDNum;    /* File number of parent. */
  662.     Boolean        createDir;    /* Should create the directory. */
  663.     char        *path;
  664. {
  665.     DIR            *unixDirPtr;
  666.     struct direct    *unixDirEntPtr;
  667.     DirIndexInfo    indexInfo;
  668.     Fslcl_DirEntry    *spriteDirEntPtr;
  669.     char        fileName[FS_MAX_NAME_LENGTH + 1];
  670.     int            newFDNum;
  671.     Fsdm_FileDescriptor    newFD;
  672.     Fsdm_FileDescriptor    *newFDPtr;
  673.     struct    stat    statBuf;
  674.     int            followLinks;
  675.     char        pathName[1024];
  676.     char        fileBlock[FS_BLOCK_SIZE];
  677.     char        indirectBlock[FS_BLOCK_SIZE];
  678.     int            *indIndexPtr = (int *)indirectBlock;
  679.     char        *suffix;
  680.     Boolean        makeDevice;
  681.     int            devType;
  682.     int            devUnit;
  683.     int            devServer;
  684.     ReturnStatus    status;
  685.  
  686.  
  687.     /*
  688.      * Get our absolute path name so we can get back if we follow a
  689.      * symbolic link.
  690.      */
  691.     (void) getwd(pathName);
  692.  
  693.     if (chdir(dirName) < 0) {
  694.     perror(dirName);
  695.     exit(1);
  696.     }
  697.  
  698.     /*
  699.      * Get a pointer to the UNIX directory.
  700.      */
  701.     unixDirPtr = opendir(".");
  702.     if (unixDirPtr == NULL) {
  703.     fprintf(stderr, "Can't open directory %s\n", dirName);
  704.     exit(1);
  705.     }
  706.     /*
  707.      * Open the Sprite directory.
  708.      */
  709.     status = OpenDir(partFID, headerPtr, dirFDPtr, &indexInfo,&spriteDirEntPtr);
  710.     if (status != SUCCESS) {
  711.     if (chdir(pathName) < 0) {
  712.         perror(pathName);
  713.         exit(1);
  714.     }
  715.     }
  716.     /*
  717.      * See if there is a "follow.links" file in this directory.  If so
  718.      * we are supposed to follow symbolic links rather than just copying
  719.      * the links.
  720.      */
  721.     if (stat("follow.links", &statBuf) < 0) {
  722.     followLinks = 0;
  723.     } else {
  724.     printf("Following links ...\n");
  725.     followLinks = 1;
  726.     }
  727.     if (createDir) {
  728.     CreateDir(indexInfo.dirBlock, 1, dirFDNum, parentFDNum);
  729.     }
  730.  
  731.     while ((unixDirEntPtr = readdir(unixDirPtr)) != NULL) {
  732.     if (unixDirEntPtr->d_namlen == 1 && 
  733.         strncmp(unixDirEntPtr->d_name, ".", 1) == 0) {
  734.         continue;
  735.     }
  736.     if (unixDirEntPtr->d_namlen == 2 && 
  737.         strncmp(unixDirEntPtr->d_name, "..", 2) == 0) {
  738.         continue;
  739.     }
  740.     strncpy(fileName, unixDirEntPtr->d_name, unixDirEntPtr->d_namlen);
  741.     fileName[unixDirEntPtr->d_namlen] = 0;
  742.     if (followLinks) {
  743.         if (stat(fileName, &statBuf) < 0) {
  744.         perror(fileName);
  745.         exit(1);
  746.         }
  747.     } else {
  748.         if (lstat(fileName, &statBuf) < 0) {
  749.         perror(fileName);
  750.         exit(1);
  751.         }
  752.     }
  753.     makeDevice = FALSE;
  754.     suffix = strstr(fileName, DEVICE_SUFFIX);
  755.     if ((suffix != NULL) && (!strcmp(suffix, DEVICE_SUFFIX)) &&
  756.         ((statBuf.st_mode & S_GFMT) == S_GFREG)) {
  757.         FILE    *fp;
  758.         char    buffer[128];
  759.         int        ok = 0;
  760.  
  761.         fp = fopen(fileName, "r");
  762.         if (fp == NULL) {
  763.         fprintf(stderr, "WARNING: Can't open %s%s: ", pathName,
  764.             fileName);
  765.         perror((char *) NULL);
  766.         continue;
  767.         }
  768.         while (fgets(buffer, 128, fp) != NULL) {
  769.         char    tmp[128];
  770.         int    n;
  771.  
  772.         n = sscanf(buffer, " %128s", tmp);
  773.         if (n < 1 || *tmp == '#') {
  774.             continue;
  775.         }
  776.         if (sscanf(buffer, " %d %d %d", &devServer, &devType, &devUnit)
  777.             != 3) {
  778.             fprintf(stderr, 
  779.             "WARNING: Device file %s%s has bad format. Skipping.\n",
  780.             pathName, fileName);
  781.             break;
  782.         }
  783.         ok = 1;
  784.         break;
  785.         }
  786.         fclose(fp);
  787.         if (!ok) {
  788.         continue;
  789.         }
  790.         makeDevice = TRUE;
  791.         *suffix = '\0';
  792.     }
  793.     newFDNum = freeFDNum;
  794.     freeFDNum++;
  795.     MarkFDBitmap(newFDNum, fdBitmapPtr);
  796.     summaryPtr->numFreeFileDesc--;
  797.     ReadFileDesc(partFID, headerPtr, newFDNum, &newFD);
  798.     newFDPtr = &newFD;
  799.  
  800.     status = AddToDirectory(partFID, headerPtr, !printOnly, &indexInfo, 
  801.         &spriteDirEntPtr, newFDNum, fileName);
  802.     if (status != SUCCESS) {
  803.         fprintf(stderr, "%s is full\n", dirName);
  804.         break;
  805.     }
  806.     if (makeDevice) {
  807.         InitDesc(newFDPtr, FS_DEVICE, 0, devServer, devType, devUnit, 0, 0,
  808.         (int) statBuf.st_mode & 07777, curTime.tv_sec);
  809.         printf("Device: %s%s (S %d, T %d, U %d)\n", path, fileName,
  810.         devServer, devType, devUnit);
  811. #ifdef sprite
  812.     } else if ((statBuf.st_mode & S_GFMT) == S_IFPDEV) {
  813.         printf("Skipping pseudo-device %s%s\n", path, fileName);
  814. #endif
  815.     } else if ((statBuf.st_mode & S_GFMT) == S_GFREG ||
  816. #ifdef sprite
  817.            ((statBuf.st_mode & S_GFMT) == S_IFRLNK)  || 
  818. #endif
  819.            (statBuf.st_mode & S_GFMT) == S_GFLNK) {
  820.         int    fd = -1;
  821.         int    blockNum;
  822.         int    toRead;
  823.         int    len;
  824.  
  825.         blockNum = 0;
  826.         if ((statBuf.st_mode & S_GFMT) == S_GFREG) {
  827.         printf("File: %s%s\n", path, fileName);
  828.         InitDesc(newFDPtr, FS_FILE, (int) statBuf.st_size, -1, -1, -1,
  829.              0, 0, (int) statBuf.st_mode & 07777, statBuf.st_mtime);
  830.         /*
  831.          * Copy the file over.
  832.          */
  833.         fd = open(fileName, 0);
  834.         if (fd < 0) {
  835.             fprintf(stderr, "WARNING: Can't open %s%s: ", pathName,
  836.             fileName);
  837.             perror((char *) NULL);
  838.             freeFDNum--;
  839.             summaryPtr->numFreeFileDesc++;
  840.             continue;
  841.         }
  842.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  843.         if (len < 0) {
  844.             fprintf(stderr, "WARNING: Can't read %s%s: ", pathName,
  845.             fileName);
  846.             perror((char *) NULL);
  847.             freeFDNum--;
  848.             summaryPtr->numFreeFileDesc++;
  849.             continue;
  850.         }
  851.         toRead = statBuf.st_size;
  852.         } else {
  853.         len = readlink(fileName, fileBlock, FS_BLOCK_SIZE);
  854.         if (len < 0) {
  855.             fprintf(stderr, "WARNING: Can't readlink %s%s: ", pathName,
  856.             fileName);
  857.             perror((char *) NULL);
  858.             freeFDNum--;
  859.             summaryPtr->numFreeFileDesc++;
  860.             continue;
  861.         }
  862.         fileBlock[len] = '\0';
  863.         InitDesc(newFDPtr, FS_SYMBOLIC_LINK, len + 1, -1, -1, -1, 
  864.              0, 0, 0777, statBuf.st_mtime);
  865. #ifdef sprite
  866.         if ((statBuf.st_mode & S_GFMT) == S_IFRLNK) { 
  867.             printf("Remote link: %s%s\n", path, fileName);
  868.         } else {
  869.             printf("Symbolic link: %s%s -> %s\n", 
  870.                 path, fileName, fileBlock);
  871.         }
  872. #else
  873.         printf("Symbolic link: %s%s -> %s\n", 
  874.             path, fileName, fileBlock);
  875. #endif
  876.         toRead = len + 1;
  877.         }
  878.  
  879.         while (len > 0) {
  880.         if (blockNum == FSDM_NUM_DIRECT_BLOCKS) {
  881.             int    i;
  882.             int    *intPtr;
  883.             /*
  884.              * Must allocate an indirect block.
  885.              */
  886.             newFDPtr->indirect[0] =
  887.             VirtToPhys(freeBlockNum * FS_FRAGMENTS_PER_BLOCK);
  888.             MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  889.                    FS_FRAGMENTS_PER_BLOCK);
  890.             freeBlockNum++;
  891.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  892.             for (i = 0, intPtr = (int *)indirectBlock; 
  893.              i < FS_BLOCK_SIZE / sizeof(int); 
  894.              i++, intPtr++) {
  895.              *intPtr = FSDM_NIL_INDEX;
  896.             }
  897.         }
  898.         if (blockNum >= FSDM_NUM_DIRECT_BLOCKS) {
  899.             indIndexPtr[blockNum - FSDM_NUM_DIRECT_BLOCKS] = 
  900.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  901.             MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  902.                    FS_FRAGMENTS_PER_BLOCK);
  903.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  904.         } else {
  905.             newFDPtr->direct[blockNum] = 
  906.                     freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  907.             if (toRead > FS_BLOCK_SIZE) {
  908.             MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  909.                        FS_FRAGMENTS_PER_BLOCK);
  910.             summaryPtr->numFreeKbytes -= FS_FRAGMENTS_PER_BLOCK;
  911.             } else {
  912.             MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  913.                        (toRead - 1) / FS_FRAGMENT_SIZE + 1);
  914.             summaryPtr->numFreeKbytes -= 
  915.                     (toRead - 1) / FS_FRAGMENT_SIZE + 1;
  916.             }
  917.         }
  918.         /*
  919.          * Write the block out to disk.
  920.          */
  921.         if (Disk_BlockWrite(partFID, headerPtr, 
  922.                     headerPtr->dataOffset + freeBlockNum,
  923.                     1, (Address)fileBlock) != 0) {
  924.             fprintf(stderr, "Couldn't write file block\n");
  925.             exit(1);
  926.         }
  927.         blockNum++;
  928.         freeBlockNum++;
  929.         if ((statBuf.st_mode & S_GFMT) == S_GFLNK) {
  930.             break;
  931.         }
  932.         toRead -= len;
  933.         len = read(fd, fileBlock, FS_BLOCK_SIZE);
  934.         if (len < 0) {
  935.             perror(fileName);
  936.             exit(1);
  937.         }
  938.         }
  939.         if (newFDPtr->indirect[0] != FSDM_NIL_INDEX) {
  940.         if (Disk_BlockWrite(partFID, headerPtr,
  941.                 newFDPtr->indirect[0] / FS_FRAGMENTS_PER_BLOCK,
  942.                 1, (Address)indirectBlock) != 0) {
  943.             fprintf(stderr, "Couldn't write indirect block\n");
  944.             exit(1);
  945.         }
  946.         }
  947.         close(fd);
  948.     } else if (statBuf.st_mode & S_GFDIR) {
  949.         char    newPath[FS_MAX_NAME_LENGTH];
  950.  
  951.         /*
  952.          * Increment the current directories link count because once
  953.          * the child gets created it will point to the parent.
  954.          */
  955.         dirFDPtr->numLinks++;
  956.         /*
  957.          * Allocate the currently free file descriptor to this directory.
  958.          */
  959.         InitDesc(newFDPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, -1, 
  960.              0, 0, (int) statBuf.st_mode & 07777, statBuf.st_mtime);
  961.         /*
  962.          * Give the directory one full block.  The directory will
  963.          * be initialized by CopyTree when we call it recursively.
  964.          */
  965.         newFDPtr->direct[0] = freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  966.         MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  967.                FS_FRAGMENTS_PER_BLOCK);
  968.         freeBlockNum++;
  969.         sprintf(newPath, "%s%s/", path, fileName);
  970.         printf("Directory: %s\n", newPath);
  971.         CopyTree(partFID, fileName, newFDNum, newFDPtr, dirFDNum, TRUE, 
  972.         newPath);
  973.     } else {
  974.         fprintf(stderr, "WARNING: %s%s is not a file or directory\n",
  975.         pathName, fileName);
  976.         freeFDNum--;
  977.         summaryPtr->numFreeFileDesc++;
  978.         continue;
  979.     }
  980.     WriteFileDesc(partFID, headerPtr, newFDNum, newFDPtr);
  981.  
  982.     }
  983.  
  984.     CloseDir(partFID, headerPtr, !printOnly, &indexInfo);
  985.  
  986.     if (chdir(pathName) < 0) {
  987.     perror(pathName);
  988.     exit(1);
  989.     }
  990.     closedir(unixDirPtr);
  991.     return;
  992. }
  993.  
  994.  
  995. /*
  996.  *----------------------------------------------------------------------
  997.  *
  998.  * SetDomainHeader --
  999.  *
  1000.  *    Compute the domain header based on the partition size and
  1001.  *    other basic disk parameters.
  1002.  *
  1003.  * Results:
  1004.  *    A return code.
  1005.  *
  1006.  * Side effects:
  1007.  *    Fill in the domain header.
  1008.  *
  1009.  *----------------------------------------------------------------------
  1010.  */
  1011. static ReturnStatus
  1012. SetDomainHeader(labelPtr, headerPtr, spriteID, partition)
  1013.     Disk_Label        *labelPtr;    /* The disk label. */
  1014.     Ofs_DomainHeader     *headerPtr;    /* Domain header to fill in */
  1015.     int         spriteID;    /* Host ID of machine with the disks */
  1016.     int         partition;    /* Index of partition to format */
  1017. {
  1018.     register Ofs_Geometry *geoPtr;/* The layout information for the disk */
  1019.  
  1020.     headerPtr->magic = OFS_DOMAIN_MAGIC;
  1021.     headerPtr->firstCylinder = labelPtr->partitions[partition].firstCylinder;
  1022.     headerPtr->numCylinders = labelPtr->partitions[partition].numCylinders;
  1023.     if (headerPtr->numCylinders <= 0) {
  1024.     fprintf(stderr, "Invalid partition size: %d cylinders.\n", 
  1025.         headerPtr->numCylinders);
  1026.     return FAILURE;
  1027.     }
  1028.     /*
  1029.      * The device.serverID from the disk is used during boot to discover
  1030.      * the host"s spriteID if reverse arp couldn't find a host ID.  The
  1031.      * unit number of disk indicates what partition of the disk this
  1032.      * domain header applies to.  For example, both the "a" and "c" partitions
  1033.      * typically start at sector zero, but only one is valid.  During boot
  1034.      * time the unit number is used to decide which partition should be
  1035.      * attached.
  1036.      */
  1037.     headerPtr->device.serverID = spriteID;
  1038.     headerPtr->device.type = -1;
  1039.     headerPtr->device.unit = partition;
  1040.     headerPtr->device.data = (ClientData)-1;
  1041.  
  1042.     geoPtr = &headerPtr->geometry;
  1043.     if (scsiDisk) {
  1044.     SetSCSIDiskGeometry(labelPtr, geoPtr);
  1045.     } else {
  1046.     SetDiskGeometry(labelPtr, geoPtr);
  1047.     }
  1048.  
  1049.     SetDomainParts(labelPtr, partition, headerPtr);
  1050.     return SUCCESS;
  1051. }
  1052.  
  1053. /*
  1054.  *----------------------------------------------------------------------
  1055.  *
  1056.  * SetSCSIDiskGeometry --
  1057.  *
  1058.  *    This computes the rotational set arrangment depending on the
  1059.  *    disk geometry.  No fancy block skewing is done.  The cylinders
  1060.  *    are divided into rotational sets that minimize the amount of
  1061.  *    wasted space.
  1062.  *
  1063.  * Results:
  1064.  *    None.
  1065.  *
  1066.  * Side effects:
  1067.  *    Fill in the geometry struct.
  1068.  *
  1069.  *----------------------------------------------------------------------
  1070.  */
  1071. static void
  1072. SetSCSIDiskGeometry(labelPtr, geoPtr)
  1073.     register Disk_Label        *labelPtr;    /* The disk label. */
  1074.     register Ofs_Geometry     *geoPtr;    /* Fancy geometry information */
  1075. {
  1076.     register int index;        /* Array index */
  1077.     int blocksPerCyl;        /* The number of blocks in a cylinder */
  1078.  
  1079.     geoPtr->numHeads = labelPtr->numHeads;
  1080.     geoPtr->sectorsPerTrack = labelPtr->numSectors;
  1081.  
  1082.     blocksPerCyl = geoPtr->sectorsPerTrack * geoPtr->numHeads /
  1083.         DISK_SECTORS_PER_BLOCK;
  1084.  
  1085.     printf("Disk has %d tracks/cyl, %d sectors/track\n",
  1086.         geoPtr->numHeads, geoPtr->sectorsPerTrack);
  1087.     printf("%d 4K Blocks fit on a cylinder with %d 512 byte sectors wasted\n",
  1088.         blocksPerCyl, geoPtr->sectorsPerTrack * geoPtr->numHeads - 
  1089.         blocksPerCyl * DISK_SECTORS_PER_BLOCK);
  1090.     geoPtr->rotSetsPerCyl = OFS_SCSI_MAPPING;
  1091.     geoPtr->blocksPerRotSet = 0;
  1092.     geoPtr->blocksPerCylinder = blocksPerCyl;
  1093.     geoPtr->tracksPerRotSet = 0;
  1094.     /*
  1095.      * Don't use rotational sorting anyway.
  1096.      */
  1097.     for (index = 0 ; index < OFS_MAX_ROT_POSITIONS ; index++) {
  1098.     geoPtr->sortedOffsets[index] = -1;
  1099.     }
  1100. }
  1101.  
  1102. /*
  1103.  *----------------------------------------------------------------------
  1104.  *
  1105.  * SetDiskGeometry --
  1106.  *
  1107.  *    This computes the rotational set arrangment depending on the
  1108.  *    disk geometry.  The basic rules for this are that filesystem blocks
  1109.  *    are skewed on successive tracks, and that the skewing pattern
  1110.  *    repeats in either 2 or 4 tracks.  This is specific to the fact that
  1111.  *    filesystem blocks are 4Kbytes.  This means that one disk track
  1112.  *    contains N/4 filesystem blocks and that one sector per track
  1113.  *    is wasted if there are an odd number of sectors per track.
  1114.  *
  1115.  * Results:
  1116.  *    None.
  1117.  *
  1118.  * Side effects:
  1119.  *    Fill in the geometry struct.
  1120.  *
  1121.  *----------------------------------------------------------------------
  1122.  */
  1123. static void
  1124. SetDiskGeometry(labelPtr, geoPtr)
  1125.     register Disk_Label        *labelPtr;    /* The disk label. */
  1126.     register Ofs_Geometry     *geoPtr;    /* Fancy geometry information */
  1127. {
  1128.     register int index;        /* Array index */
  1129.     int numBlocks;        /* The number of blocks in a rotational set */
  1130.     int tracksPerSet = 0;    /* Total number of tracks in a rotational set */
  1131.     int numTracks;        /* The number of tracks in the set so far */
  1132.     int extraSectors;        /* The number of leftover sectors in a track */
  1133.     int offset;            /* The sector offset within a track */
  1134.     int startingOffset;        /* The offset of the first block in a track */
  1135.     int offsetIncrement = 0;    /* The skew of the starting offset on each
  1136.                  * successive track of the rotational set */
  1137.     Boolean overlap = FALSE;    /* TRUE if filesystem blocks overlap tracks */
  1138.  
  1139.     geoPtr->numHeads = labelPtr->numHeads;
  1140.     geoPtr->sectorsPerTrack = labelPtr->numSectors;
  1141.  
  1142.     /*
  1143.      * Figure out some basic parameters of the rotational set.  The number
  1144.      * of tracks in the set is either 2 or 4.  If 2, then the blocks on
  1145.      * successive tracks are skewed by 1/2 a filesystem block.  If 4,
  1146.      * blocks are skewed by 1/4 block.  A 4 track rotational set is best
  1147.      * becasue there are more rotational positions.  If, however, it
  1148.      * causes 2 or 3 wasted tracks at the end, or if blocks naturally
  1149.      * overlap by 1/2 block, then only 2 tracks per rotational set are
  1150.      * used.
  1151.      */
  1152.     switch(geoPtr->numHeads % 4) {
  1153.     case 0:
  1154.     case 1: {
  1155.         extraSectors = geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK;
  1156.         if (extraSectors < DISK_SECTORS_PER_BLOCK/4) {
  1157.         /*
  1158.          * Not enough extra sectors to overlap blocks onto the
  1159.          * next track.  The blocks will fit evenly on a track,
  1160.          * but the blocks on the following tracks will be skewed.
  1161.          */
  1162.         tracksPerSet = 4;
  1163.         overlap = FALSE;
  1164.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  1165.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK/2) {
  1166.         /*
  1167.          * Enough to overlap the first 1/4 block onto the next track.
  1168.          */
  1169.         tracksPerSet = 4;
  1170.         overlap = TRUE;
  1171.         offsetIncrement = DISK_SECTORS_PER_BLOCK * 3/4;
  1172.         } else if (extraSectors < DISK_SECTORS_PER_BLOCK * 3/4) {
  1173.         /*
  1174.          * Enough to overlap 1/2 block.
  1175.          */
  1176.         tracksPerSet = 2;
  1177.         overlap = TRUE;
  1178.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  1179.         } else {
  1180.         /*
  1181.          * Enough to overlap 3/4 block.
  1182.          */
  1183.         tracksPerSet = 4;
  1184.         overlap = TRUE;
  1185.         offsetIncrement = DISK_SECTORS_PER_BLOCK/4;
  1186.         }
  1187.         break;
  1188.     }
  1189.     case 2:
  1190.     case 3: {
  1191.         /*
  1192.          * Instead of wasting 2 or 3 tracks to have a 4 track rotational
  1193.          * set, the rotational set is only 2 tracks long.  Also see if
  1194.          * the blocks naturally overlap by 1/2 block.
  1195.          */
  1196.         tracksPerSet = 2;
  1197.         offsetIncrement = DISK_SECTORS_PER_BLOCK/2;
  1198.         if ((geoPtr->sectorsPerTrack % DISK_SECTORS_PER_BLOCK) <
  1199.               DISK_SECTORS_PER_BLOCK/2) {
  1200.         overlap = FALSE;
  1201.         } else {
  1202.         overlap = TRUE;
  1203.         }
  1204.     }
  1205.     }
  1206.     if (!overlapBlocks) {
  1207.     overlap = FALSE;
  1208.     offsetIncrement = 0;
  1209.     }
  1210.     printf("overlap %s, offsetIncrement %d\n", (overlap ? "TRUE" : "FALSE"),
  1211.               offsetIncrement);
  1212.     /*
  1213.      * Determine rotational position of the blocks in the rotational set.
  1214.      */
  1215.     extraSectors = geoPtr->sectorsPerTrack;
  1216.     startingOffset = 0;
  1217.     offset = startingOffset;
  1218.     for (numBlocks = 0, numTracks = 0 ; ; ) {
  1219.     if (extraSectors >= DISK_SECTORS_PER_BLOCK) {
  1220.         /*
  1221.          * Ok to fit in another filesystem block on this track.
  1222.          */
  1223.         geoPtr->blockOffset[numBlocks] = offset;
  1224.         numBlocks++;    
  1225.         offset += DISK_SECTORS_PER_BLOCK;
  1226.         extraSectors -= DISK_SECTORS_PER_BLOCK;
  1227.     } else {
  1228.         /*
  1229.          * The current block has to take up room on the next track.
  1230.          */
  1231.         numTracks++;
  1232.         if (numTracks < tracksPerSet) {
  1233.         /*
  1234.          * Ok to go to the next track.
  1235.          */
  1236.         startingOffset += offsetIncrement;
  1237.         if (overlap) {
  1238.             /*
  1239.              * If the current block can overlap to the next track,
  1240.              * use the current offset.  Because of the overlap
  1241.              * there are fewer sectors available for blocks on
  1242.              * the next track.
  1243.              */
  1244.             geoPtr->blockOffset[numBlocks] = offset;
  1245.             numBlocks++;
  1246.             extraSectors = geoPtr->sectorsPerTrack - startingOffset;
  1247.         }
  1248.         offset = startingOffset + numTracks * geoPtr->sectorsPerTrack;
  1249.         if (!overlap) {
  1250.             /*
  1251.              * If no overlap the whole next track is available.
  1252.              */
  1253.             extraSectors = geoPtr->sectorsPerTrack;
  1254.         }
  1255.         } else {
  1256.         /*
  1257.          * Done.
  1258.          */
  1259.         for (index = numBlocks; index < OFS_MAX_ROT_POSITIONS; index++){
  1260.             geoPtr->blockOffset[index] = -1;
  1261.         }
  1262.         break;
  1263.         }
  1264.     }
  1265.     }
  1266.     geoPtr->blocksPerRotSet = numBlocks;
  1267.     geoPtr->tracksPerRotSet = tracksPerSet;
  1268.     geoPtr->rotSetsPerCyl = geoPtr->numHeads / tracksPerSet;
  1269.     geoPtr->blocksPerCylinder = numBlocks * geoPtr->rotSetsPerCyl;
  1270.  
  1271.     /*
  1272.      * Now the rotational positions have to be sorted so that rotationally
  1273.      * optimal blocks can be found.  The array sortedOffsets is set so
  1274.      * that the I'th element has the index into blockOffset which contains
  1275.      * the I'th rotational position, eg.
  1276.      *    blockOffset    sortedOffsets
  1277.      *        0 (+0)        0
  1278.      *        8 (+0)        2
  1279.      *        4 (+17)        1
  1280.      *       12 (+17)        3
  1281.      */
  1282.  
  1283.     offsetIncrement = DISK_SECTORS_PER_BLOCK / tracksPerSet;
  1284.     for (index = 0 ; index < OFS_MAX_ROT_POSITIONS ; index++) {
  1285.     geoPtr->sortedOffsets[index] = -1;
  1286.     }
  1287.     for (index = 0 ; index < numBlocks ; index++) {
  1288.     offset = geoPtr->blockOffset[index] % geoPtr->sectorsPerTrack;
  1289.     geoPtr->sortedOffsets[offset/offsetIncrement] = index;
  1290.     }
  1291. }
  1292.  
  1293. /*
  1294.  *----------------------------------------------------------------------
  1295.  *
  1296.  * SetDomainParts --
  1297.  *
  1298.  *    Set up the way the domain is divided into 4 areas:  the bitmap
  1299.  *    for the file descriptors, the file descriptors, the bitmap for
  1300.  *    the data blocks, and the data blocks.
  1301.  *
  1302.  * Results:
  1303.  *    The geometry information is completed.
  1304.  *
  1305.  * Side effects:
  1306.  *    None.
  1307.  *
  1308.  *----------------------------------------------------------------------
  1309.  */
  1310. static void
  1311. SetDomainParts(labelPtr, partition, headerPtr)
  1312.     register Disk_Label        *labelPtr;    /* The disk label. */
  1313.     int partition;
  1314.     register Ofs_DomainHeader *headerPtr;
  1315. {
  1316.     register Ofs_Geometry *geoPtr;
  1317.     int numFiles;        /* Number of files computed from the size */
  1318.     int numBlocks;        /* Number of blocks in the partition.  This
  1319.                  * is computed and then dolled out to the
  1320.                  * different things stored in the partition */
  1321.     int offset;            /* Block offset within partition */
  1322.     int bitmapBytes;        /* Number of bytes taken up by a bitmap */
  1323.     int reservedBlocks;        /* Number of blocks reserved at beginning
  1324.                  * of partition */
  1325.     int maxSector;
  1326.     int numCylinders;
  1327.     int bytesPerCylinder;
  1328.  
  1329.     /*
  1330.      * Set aside a number of blocks at the begining of the partition for
  1331.      * things like the super block, the boot program, and the domain header.
  1332.      */
  1333.     geoPtr = &headerPtr->geometry;
  1334.     maxSector = labelPtr->labelSector;
  1335.     maxSector = Max(maxSector,labelPtr->bootSector + labelPtr->numBootSectors);
  1336.     maxSector = Max(maxSector,labelPtr->summarySector
  1337.     + labelPtr->numSummarySectors);
  1338.     maxSector = Max(maxSector,labelPtr->domainSector
  1339.     + labelPtr->numDomainSectors);
  1340.     numCylinders = labelPtr->partitions[partition].numCylinders;
  1341.     if (scsiDisk) {
  1342.     /*
  1343.      * For a scsi disk just reserve whole cylinders.
  1344.      */
  1345.     int cylinders;
  1346.     cylinders = maxSector / (geoPtr->sectorsPerTrack * geoPtr->numHeads);
  1347.     if ((maxSector % (geoPtr->sectorsPerTrack * geoPtr->numHeads)) != 0) {
  1348.         cylinders++;
  1349.     }
  1350.     reservedBlocks = cylinders * geoPtr->blocksPerCylinder;
  1351.     numBlocks = geoPtr->blocksPerCylinder * numCylinders - reservedBlocks;
  1352.      } else {
  1353.     /*
  1354.      * If we are using rotational sets then reserve whole sets.
  1355.      */
  1356.     int sets;
  1357.     sets = maxSector / (geoPtr->tracksPerRotSet * geoPtr->sectorsPerTrack);
  1358.     if ((maxSector % (geoPtr->tracksPerRotSet * geoPtr->sectorsPerTrack)) 
  1359.     != 0) {
  1360.         sets++;
  1361.     }
  1362.     reservedBlocks = sets * geoPtr->blocksPerRotSet;
  1363.     numBlocks = geoPtr->blocksPerCylinder * numCylinders - reservedBlocks;
  1364.     }
  1365.     printf("Reserving %d blocks for domain header, etc.\n", reservedBlocks);
  1366.     /*
  1367.      * Determine the number of filesystem blocks available and compute a
  1368.      * first guess at the number of file descriptors.  If at the end of
  1369.      * the computation things don't fit nicely, then the number of files
  1370.      * is changed and the computation is repeated.
  1371.      */
  1372.     numFiles = 0;
  1373.     do {
  1374.     if (numFiles == 0) {
  1375.         numFiles = numBlocks * DISK_KBYTES_PER_BLOCK / kbytesToFileDesc;
  1376.     }
  1377.     numFiles          &= ~(FSDM_FILE_DESC_PER_BLOCK-1);
  1378.     offset              = reservedBlocks;
  1379.  
  1380.     assert(numFiles > 0);
  1381.     headerPtr->fdBitmapOffset = offset;
  1382.     bitmapBytes          = (numFiles - 1) / BITS_PER_BYTE + 1;
  1383.     headerPtr->fdBitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  1384.     numBlocks          -= headerPtr->fdBitmapBlocks;
  1385.     offset              += headerPtr->fdBitmapBlocks;
  1386.  
  1387.     headerPtr->fileDescOffset = offset;
  1388.     headerPtr->numFileDesc      = numFiles;
  1389.     numBlocks          -= numFiles / FSDM_FILE_DESC_PER_BLOCK;
  1390.     offset              += numFiles / FSDM_FILE_DESC_PER_BLOCK;
  1391.     /*
  1392.      * The data blocks will start on a cylinder.  Try the next
  1393.      * cylinder boundary after the start of the bitmap. If the
  1394.      * bitmap won't fit in a cylinder then steal a cylinder from the
  1395.      * data blocks.
  1396.      */
  1397.     headerPtr->bitmapOffset      = offset;
  1398.     headerPtr->dataOffset      = ((offset-1) / geoPtr->blocksPerCylinder + 1)
  1399.                      * geoPtr->blocksPerCylinder;
  1400.     headerPtr->dataBlocks      = headerPtr->numCylinders *
  1401.                       geoPtr->blocksPerCylinder -
  1402.                       headerPtr->dataOffset;
  1403.     bytesPerCylinder      = (geoPtr->blocksPerCylinder + 1) / 2;
  1404.     bitmapBytes          = bytesPerCylinder * (headerPtr->dataBlocks / 
  1405.                     geoPtr->blocksPerCylinder); 
  1406.  
  1407.     headerPtr->bitmapBlocks      = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  1408.     while (headerPtr->bitmapBlocks > 
  1409.         headerPtr->dataOffset - headerPtr->bitmapOffset) {
  1410.         /*
  1411.          * If the bit map blocks won't fit in the number cylinders
  1412.          * we've allocated to them then we need to
  1413.          * steal a cylinder from the data blocks.
  1414.          */
  1415.         headerPtr->dataOffset += geoPtr->blocksPerCylinder;
  1416.         headerPtr->dataBlocks -= geoPtr->blocksPerCylinder;
  1417.         bitmapBytes -= geoPtr->blocksPerCylinder * bytesPerCylinder;
  1418.         bitmapBytes          = bytesPerCylinder * (headerPtr->dataBlocks / 
  1419.                     geoPtr->blocksPerCylinder); 
  1420.         headerPtr->bitmapBlocks = (bitmapBytes - 1) / FS_BLOCK_SIZE + 1;
  1421.     }
  1422.     /*
  1423.      * Check the size of the bit map against space available for it
  1424.      * between the end of the file descriptors and the start of the
  1425.      * data blocks.
  1426.      */
  1427.     if (headerPtr->dataOffset - headerPtr->bitmapOffset <
  1428.         headerPtr->bitmapBlocks) {
  1429.         int numBlocksNeeded;
  1430.         /*
  1431.          * Need more blocks to hold the bitmap.  Reduce the number
  1432.          * of file descriptors to get the blocks and re-iterate.
  1433.          */
  1434.         numBlocksNeeded = headerPtr->bitmapBlocks -
  1435.         (headerPtr->dataOffset - headerPtr->bitmapOffset);
  1436.         numFiles -= numBlocksNeeded * FSDM_FILE_DESC_PER_BLOCK;
  1437.     } else if (headerPtr->dataOffset - headerPtr->bitmapOffset >
  1438.             headerPtr->bitmapBlocks) {
  1439.         int extraBlocks;
  1440.         /*
  1441.          * There are extra blocks between the end of the file descriptors
  1442.          * and the start of the bitmap.  Increase the number of
  1443.          * file descriptors and re-iterate.
  1444.          */
  1445.         extraBlocks = headerPtr->dataOffset - headerPtr->bitmapOffset -
  1446.             headerPtr->bitmapBlocks;
  1447.         numFiles += extraBlocks * FSDM_FILE_DESC_PER_BLOCK;
  1448.     }
  1449.     } while (headerPtr->dataOffset - headerPtr->bitmapOffset !=
  1450.         headerPtr->bitmapBlocks);
  1451.     headerPtr->dataCylinders    = headerPtr->dataBlocks /
  1452.                   geoPtr->blocksPerCylinder ;
  1453. }
  1454.  
  1455. /*
  1456.  *----------------------------------------------------------------------
  1457.  *
  1458.  * SetSummaryInfo --
  1459.  *
  1460.  *    Initialize the summary information for the domain.  
  1461.  *
  1462.  * Results:
  1463.  *    A return code.
  1464.  *
  1465.  * Side effects:
  1466.  *    Fill in the summary info.
  1467.  *
  1468.  *----------------------------------------------------------------------
  1469.  */
  1470. static void
  1471. SetSummaryInfo(headerPtr, summaryPtr)
  1472.     Ofs_DomainHeader *headerPtr;    /* Domain header to summarize */
  1473.     Ofs_SummaryInfo *summaryPtr;    /* Summary info to fill in */
  1474. {
  1475.  
  1476.     bzero((Address)summaryPtr, sizeof(Ofs_SummaryInfo));
  1477.  
  1478.     strcpy(summaryPtr->domainPrefix, "(new domain)");
  1479.     /*
  1480.      * 20 KB is already allocated, 4 for the root directory,
  1481.      * 8 for lost+found, and 8 for .fscheck.out
  1482.      */
  1483.     summaryPtr->numFreeKbytes = headerPtr->dataBlocks * (FS_BLOCK_SIZE / 1024)
  1484.                 - 20;
  1485.     /*
  1486.      * 5 file descriptors are already used, 0 and 1 are reserved,
  1487.      * 2 is for the root, 3 is for lost+found, and 4 is for .fscheck.out
  1488.      */
  1489.     summaryPtr->numFreeFileDesc = headerPtr->numFileDesc - 5;
  1490.     /*
  1491.      * The summary state field is unused.
  1492.      */
  1493.     summaryPtr->state = 0;
  1494.     /*
  1495.      * The domain number under which this disk partition is mounted is
  1496.      * recorded on disk so servers re-attach disks under the same "name".
  1497.      * We set it to the special value so it gets a new number assigned
  1498.      * when it is first attached.
  1499.      */
  1500.     summaryPtr->domainNumber = -1;
  1501.     /*
  1502.      * The flags field is used to record whether or not the disk has been
  1503.      * safely "sync"ed to disk upon shutdown.
  1504.      */
  1505.     summaryPtr->flags = 0;
  1506.     summaryPtr->attachSeconds = 0;
  1507.     summaryPtr->detachSeconds = 0;
  1508.     summaryPtr->fixCount = 0;
  1509. }
  1510.  
  1511. /*
  1512.  *----------------------------------------------------------------------
  1513.  *
  1514.  * WriteAllFileDescs --
  1515.  *
  1516.  *    Write out all of the file descriptors to disk.
  1517.  *
  1518.  * Results:
  1519.  *    SUCCESS if the descriptors were written, FAILURE otherwise.
  1520.  *
  1521.  * Side effects:
  1522.  *    None.
  1523.  *
  1524.  *----------------------------------------------------------------------
  1525.  */
  1526. static ReturnStatus
  1527. WriteAllFileDescs(partFID, headerPtr)
  1528.     int partFID;    /* File handle for partition to format */
  1529.     register Ofs_DomainHeader *headerPtr;
  1530. {
  1531.     ReturnStatus status;
  1532.     char *bitmap;
  1533.     char block[FS_BLOCK_SIZE];
  1534.     register Fsdm_FileDescriptor *fileDescPtr;
  1535.     register int index;
  1536.     int j;
  1537.  
  1538.     bitmap = MakeFileDescBitmap(headerPtr);
  1539.     if (!printOnly) {
  1540.     status = Disk_BlockWrite(partFID, headerPtr, headerPtr->fdBitmapOffset,
  1541.                 headerPtr->fdBitmapBlocks, (Address)bitmap);
  1542.     if (status != SUCCESS) {
  1543.         printf("Couldn't write bitmap\n");
  1544.         return(status);
  1545.     }
  1546.     }
  1547.     /*
  1548.      * Make the first block of file descriptors.  This contains some
  1549.      * canned file descriptors for the root, bad block file, the
  1550.      * lost and found directory and fscheck's output file.  
  1551.      */
  1552.     bzero(block, FS_BLOCK_SIZE);
  1553.     for (index = 0;
  1554.          index < FSDM_FILE_DESC_PER_BLOCK;
  1555.      index++ ) {
  1556.     fileDescPtr = (Fsdm_FileDescriptor *)((int)block +
  1557.                        index * FSDM_MAX_FILE_DESC_SIZE);
  1558.     fileDescPtr->magic = FSDM_FD_MAGIC;
  1559.     if (index < FSDM_BAD_BLOCK_FILE_NUMBER) {
  1560.         fileDescPtr->flags = FSDM_FD_RESERVED;
  1561.     } else if (index == FSDM_BAD_BLOCK_FILE_NUMBER) {
  1562.         InitDesc(fileDescPtr, FS_FILE, 0, -1, -1, -1, 0, 0, 0, 
  1563.         curTime.tv_sec);
  1564.     } else if (index == FSDM_ROOT_FILE_NUMBER) {
  1565.         InitDesc(fileDescPtr, FS_DIRECTORY, FS_BLOCK_SIZE, -1, -1, -1, 0,
  1566.             0, 0755, curTime.tv_sec);
  1567.         /*
  1568.          * Place the data in the first file system block.
  1569.          */
  1570.         fileDescPtr->direct[0] = 0;
  1571.     } else if (index == FSDM_LOST_FOUND_FILE_NUMBER) {
  1572.         InitDesc(fileDescPtr, FS_DIRECTORY, 2 * FS_BLOCK_SIZE,-1, -1, -1, 0,
  1573.             0, 0777, curTime.tv_sec);
  1574.         for (j = 0; j < OFS_NUM_LOST_FOUND_BLOCKS ; j++) {
  1575.         fileDescPtr->direct[j] = FS_FRAGMENTS_PER_BLOCK 
  1576.             * (j + 1);
  1577.         }
  1578.     } else if (index == FSDM_LOST_FOUND_FILE_NUMBER+1) {
  1579.         InitDesc(fileDescPtr, FS_FILE, 2 * FS_BLOCK_SIZE, -1, -1, -1, 0,
  1580.             0, 0755, curTime.tv_sec);
  1581.         for (j = 0; j < 2 ; j++) {
  1582.         fileDescPtr->direct[j] = FS_FRAGMENTS_PER_BLOCK 
  1583.             * (j + 1 + OFS_NUM_LOST_FOUND_BLOCKS);
  1584.         }
  1585.     } else {
  1586.         fileDescPtr->flags = FSDM_FD_FREE;
  1587.     }
  1588.     }
  1589.     if (!printOnly) {
  1590.     /*
  1591.      * Write out the first, specially hand crafted, block of file
  1592.      * descriptors.
  1593.      */
  1594.     status = Disk_BlockWrite(partFID, headerPtr, headerPtr->fileDescOffset,
  1595.                     1, (Address)block);
  1596.     if (status != SUCCESS) {
  1597.         return(status);
  1598.     }
  1599.     /*
  1600.      * Redo the block for the remaining file descriptors
  1601.      */
  1602.     bzero(block, FS_BLOCK_SIZE);
  1603.     for (index = 0;
  1604.          index < FSDM_FILE_DESC_PER_BLOCK;
  1605.          index++ ) {
  1606.         fileDescPtr = (Fsdm_FileDescriptor *)((int)block + index *
  1607.                            FSDM_MAX_FILE_DESC_SIZE);
  1608.         fileDescPtr->magic = FSDM_FD_MAGIC;
  1609.         fileDescPtr->flags = FSDM_FD_FREE;
  1610.     }
  1611.     /*
  1612.      * Write out the remaining file descriptors.
  1613.      */
  1614.     for (index = FSDM_FILE_DESC_PER_BLOCK;
  1615.          index < headerPtr->numFileDesc;
  1616.          index += FSDM_FILE_DESC_PER_BLOCK) {
  1617.         status = Disk_BlockWrite(partFID, headerPtr,
  1618.              headerPtr->fileDescOffset + (index/FSDM_FILE_DESC_PER_BLOCK),
  1619.              1, (Address)block);
  1620.         if (status != SUCCESS) {
  1621.         return(status);
  1622.         }
  1623.     }
  1624.     } else {
  1625.     status = SUCCESS;
  1626.     }
  1627.     return(status);
  1628. }
  1629.  
  1630. /*
  1631.  *----------------------------------------------------------------------
  1632.  *
  1633.  * MakeFileDescBitmap --
  1634.  *
  1635.  *    Compute out the bitmap for file descriptor array to disk.
  1636.  *
  1637.  * Results:
  1638.  *    None.
  1639.  *
  1640.  * Side effects:
  1641.  *    None.
  1642.  *
  1643.  *----------------------------------------------------------------------
  1644.  */
  1645. static char *
  1646. MakeFileDescBitmap(headerPtr)
  1647.     register Ofs_DomainHeader *headerPtr;
  1648. {
  1649.     register char *bitmap;
  1650.     register int index;
  1651.  
  1652.     /*
  1653.      * Allocate and initialize the bitmap to all 0"s to mean all free.
  1654.      */
  1655.     bitmap = (char *)malloc((unsigned) headerPtr->fdBitmapBlocks *
  1656.                  FS_BLOCK_SIZE);
  1657.     bzero((Address)bitmap, headerPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  1658.  
  1659.     /*
  1660.      * Reserve file descriptors 0, 1, 2, 3, and 4. File number 0 is not used at 
  1661.      * all in the filesystem.  File number 1 is for the file with bad blocks.
  1662.      * File number 2 (FSDM_ROOT_FILE_NUMBER) is the domain's root directory.
  1663.      * File number 3 (FS_LOST_FOUND_NUMBER) is the directory where lost
  1664.      * files are stored.
  1665.      * File number 4 is for fscheck's output.
  1666.      *
  1667.      * IF THIS CHANGES remember to fix SetSummaryInfo
  1668.      */
  1669.     bitmap[0] |= 0xf8;
  1670.     freeFDNum = 5;
  1671.     /*
  1672.      * Set the bits in the map at the end that don't correspond to
  1673.      * any existing file descriptors.
  1674.      */
  1675.     index = headerPtr->numFileDesc / BITS_PER_BYTE;
  1676.     if (headerPtr->numFileDesc % BITS_PER_BYTE) {
  1677.     register int bitIndex;
  1678.     /*
  1679.      * Take care the last byte that only has part of its bits set.
  1680.      */
  1681.     for (bitIndex = headerPtr->numFileDesc % BITS_PER_BYTE;
  1682.          bitIndex < BITS_PER_BYTE;
  1683.          bitIndex++) {
  1684.         bitmap[index] |= 1 << ((BITS_PER_BYTE - 1) - bitIndex);
  1685.     }
  1686.     index++;
  1687.     }
  1688.     index++;
  1689.     for ( ; index < headerPtr->fdBitmapBlocks * FS_BLOCK_SIZE; index++) {
  1690.     bitmap[index] = 0xff;
  1691.     }
  1692.  
  1693.     if (printOnly) {
  1694.     Disk_PrintFileDescBitmap(headerPtr, bitmap);
  1695.     }
  1696.     return(bitmap);
  1697. }
  1698.  
  1699. /*
  1700.  *----------------------------------------------------------------------
  1701.  *
  1702.  * WriteBitmap --
  1703.  *
  1704.  *    Write out the bitmap for the data blocks.  This knows that the
  1705.  *    first 4K is allocated to the root directory, 8K is
  1706.  *    allocated to lost and found, and 8K to .fscheck.out.
  1707.  *
  1708.  * Results:
  1709.  *    A return code from the writes.
  1710.  *
  1711.  * Side effects:
  1712.  *    Write the bitmap.
  1713.  *
  1714.  *----------------------------------------------------------------------
  1715.  */
  1716. static ReturnStatus
  1717. WriteBitmap(partFID, headerPtr)
  1718.     int partFID;
  1719.     register Ofs_DomainHeader *headerPtr;
  1720. {
  1721.     ReturnStatus status;
  1722.     char *bitmap;
  1723.  
  1724.     bitmap = (char *)malloc((unsigned) headerPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1725.     bzero(bitmap, headerPtr->bitmapBlocks * FS_BLOCK_SIZE);
  1726.     /*
  1727.      * Set the bits corresponding to the 4K used for the root directory,
  1728.      * the 8K reserved for lost and found, and the 8K reserved for
  1729.      * .fscheck.out.
  1730.      *   ________
  1731.      *    |0______7|    Bits are numbered like this in a byte.
  1732.      *
  1733.      * IF THIS CHANGES remember to fix SetSummaryInfo()
  1734.      */
  1735.     bitmap[0] |= 0xff;
  1736.     bitmap[1] |= 0xff;
  1737.     bitmap[2] |= 0xf0;
  1738.     freeBlockNum = 5;
  1739.     if (printOnly) {
  1740.     Disk_PrintDataBlockBitmap(headerPtr, bitmap);
  1741.     status = SUCCESS;
  1742.     } else {
  1743.     status = Disk_BlockWrite(partFID, headerPtr, headerPtr->bitmapOffset,
  1744.                 headerPtr->bitmapBlocks, (Address)bitmap);
  1745.     }
  1746.     return(status);
  1747. }
  1748.  
  1749. /*
  1750.  *----------------------------------------------------------------------
  1751.  *
  1752.  * WriteRootDirectory --
  1753.  *
  1754.  *    Write the data blocks of the root directory.
  1755.  *
  1756.  * Results:
  1757.  *    A return code from the writes.
  1758.  *
  1759.  * Side effects:
  1760.  *    Write the root directory"s data block.
  1761.  *
  1762.  *----------------------------------------------------------------------
  1763.  */
  1764. static ReturnStatus
  1765. WriteRootDirectory(partFID, headerPtr, fdPtr)
  1766.     int             partFID;    /* Raw disk handle. */
  1767.     register Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  1768.     Fsdm_FileDescriptor        *fdPtr;        /* Root file desc */
  1769. {
  1770.     ReturnStatus     status;
  1771.     char         block[FS_BLOCK_SIZE];
  1772.     Fslcl_DirEntry     *dirEntryPtr;
  1773.     int         i;
  1774.     DirIndexInfo    indexInfo;
  1775.  
  1776.     CreateDir(block, 1, FSDM_ROOT_FILE_NUMBER, FSDM_ROOT_FILE_NUMBER);
  1777.     if (printOnly) {
  1778.     int offset;
  1779.     printf("Root Directory\n");
  1780.     offset = 0;
  1781.     for (i = 0; i < 4; i++) {
  1782.         dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  1783.         Disk_PrintDirEntry(dirEntryPtr);
  1784.         offset += dirEntryPtr->recordLength;
  1785.     }
  1786.     } else {
  1787.     status = Disk_BlockWrite(partFID, headerPtr, headerPtr->dataOffset,
  1788.         1, block);
  1789.     if (status != 0) {
  1790.         fprintf(stderr, "WriteRootDirectory: Couldn't write directory\n");
  1791.     }
  1792.     }
  1793.     status = OpenDir(partFID, headerPtr, fdPtr, &indexInfo, &dirEntryPtr);
  1794.     if (status != SUCCESS) {
  1795.     fprintf(stderr, "Can't open root file descriptor\n");
  1796.     return status;
  1797.     }
  1798.     status = AddToDirectory(partFID, headerPtr, !printOnly, &indexInfo, 
  1799.             &dirEntryPtr, FSDM_LOST_FOUND_FILE_NUMBER, 
  1800.             "lost+found");
  1801.     if (status != SUCCESS) {
  1802.     fprintf(stderr, "Can't add lost+found to root directory.\n");
  1803.     return status;
  1804.     }
  1805.     fdPtr->numLinks++;
  1806.     status = AddToDirectory(partFID, headerPtr, !printOnly, &indexInfo,
  1807.             &dirEntryPtr, FSDM_LOST_FOUND_FILE_NUMBER + 1, 
  1808.             ".fscheck.out");
  1809.     if (status != SUCCESS) {
  1810.     fprintf(stderr, "Can't add .fscheck.out to root directory.\n");
  1811.     return status;
  1812.     }
  1813.     CloseDir(partFID, headerPtr, !printOnly, &indexInfo);
  1814.     return(status);
  1815. }
  1816.  
  1817. /*
  1818.  *----------------------------------------------------------------------
  1819.  *
  1820.  * WriteLostFoundDirectory --
  1821.  *
  1822.  *    Write the data blocks of the lost and found directory.
  1823.  *
  1824.  * Results:
  1825.  *    A return code from the writes.
  1826.  *
  1827.  * Side effects:
  1828.  *    Write the root directory"s data block.
  1829.  *
  1830.  *----------------------------------------------------------------------
  1831.  */
  1832. static ReturnStatus
  1833. WriteLostFoundDirectory(partFID, headerPtr)
  1834.     int partFID;
  1835.     register Ofs_DomainHeader *headerPtr;
  1836. {
  1837.     ReturnStatus     status = SUCCESS;
  1838.     char         block[OFS_NUM_LOST_FOUND_BLOCKS * FS_BLOCK_SIZE];
  1839.     Fslcl_DirEntry     *dirEntryPtr;
  1840.     int         i;
  1841.  
  1842.     CreateDir(block, OFS_NUM_LOST_FOUND_BLOCKS, FSDM_LOST_FOUND_FILE_NUMBER, 
  1843.     FSDM_ROOT_FILE_NUMBER);
  1844.     if (printOnly) {
  1845.     int offset;
  1846.     printf("lost+found Directory\n");
  1847.     offset = 0;
  1848.     for (i = 0; i < 4; i++) {
  1849.         dirEntryPtr = (Fslcl_DirEntry *)((int)block + offset);
  1850.         Disk_PrintDirEntry(dirEntryPtr);
  1851.         offset += dirEntryPtr->recordLength;
  1852.     }
  1853.     } else {
  1854.     status = Disk_BlockWrite(partFID, headerPtr, headerPtr->dataOffset + 1,
  1855.             OFS_NUM_LOST_FOUND_BLOCKS, block);
  1856.     if (status != 0) {
  1857.         fprintf(stderr, 
  1858.         "WriteLostFoundDirectory: Couldn't write directory\n");
  1859.     }
  1860.     }
  1861.     return(status);
  1862. }
  1863.  
  1864. /*
  1865.  *----------------------------------------------------------------------
  1866.  *
  1867.  * InitDesc --
  1868.  *
  1869.  *    Set up a file descriptor as allocated.
  1870.  *
  1871.  * Results:
  1872.  *    None.
  1873.  *
  1874.  * Side effects:
  1875.  *    File descriptor fields filled in.
  1876.  *
  1877.  *----------------------------------------------------------------------
  1878.  */
  1879. static void
  1880. InitDesc(fileDescPtr, fileType, numBytes, devServer, devType, devUnit, uid,
  1881.     gid, permissions, time)
  1882.     Fsdm_FileDescriptor    *fileDescPtr;
  1883.     int            fileType;
  1884.     int            numBytes;
  1885.     int            devServer;
  1886.     int            devType;
  1887.     int            devUnit;
  1888.     int            uid;
  1889.     int            gid;
  1890.     int            permissions;
  1891.     long        time;
  1892. {
  1893.     int        index;
  1894.  
  1895.     fileDescPtr->flags = FSDM_FD_ALLOC;
  1896.     fileDescPtr->fileType = fileType;
  1897.     fileDescPtr->permissions = permissions;
  1898.     fileDescPtr->uid = uid;
  1899.     fileDescPtr->gid = gid;
  1900.     fileDescPtr->lastByte = numBytes - 1;
  1901.     fileDescPtr->firstByte = -1;
  1902.     if (fileType == FS_DIRECTORY) {
  1903.     fileDescPtr->numLinks = 2;
  1904.     } else {
  1905.     fileDescPtr->numLinks = 1;
  1906.     }
  1907.     fileDescPtr->devServerID = devServer;
  1908.     fileDescPtr->devType = devType;
  1909.     fileDescPtr->devUnit = devUnit;
  1910.  
  1911.     /*
  1912.      * Set the time stamps.  This assumes that universal time,
  1913.      * not local time, is used for time stamps.
  1914.      */
  1915.     fileDescPtr->createTime = (int) time;
  1916.     fileDescPtr->accessTime = (int) time;
  1917.     fileDescPtr->descModifyTime = (int) time;
  1918.     fileDescPtr->dataModifyTime = (int) time;
  1919.  
  1920.     /*
  1921.      * Place the data in the first filesystem block.
  1922.      */
  1923.     for (index = 0; index < FSDM_NUM_DIRECT_BLOCKS ; index++) {
  1924.     fileDescPtr->direct[index] = FSDM_NIL_INDEX;
  1925.     }
  1926.     for (index = 0; index < FSDM_NUM_INDIRECT_BLOCKS ; index++) {
  1927.     fileDescPtr->indirect[index] = FSDM_NIL_INDEX;
  1928.     }
  1929.     if (numBytes > 0) {
  1930.     int    numBlocks;
  1931.  
  1932.     numBlocks = (numBytes - 1) / FS_BLOCK_SIZE + 1;
  1933.     if (numBlocks > FSDM_NUM_DIRECT_BLOCKS) {
  1934.         fileDescPtr->numKbytes = (numBlocks + 1) * (FS_BLOCK_SIZE / 1024);
  1935.     } else {
  1936.         fileDescPtr->numKbytes = (numBytes + 1023) / 1024;
  1937.     }
  1938.     } else {
  1939.     fileDescPtr->numKbytes = 0;
  1940.     }
  1941.  
  1942.     fileDescPtr->version = 1;
  1943. }
  1944.  
  1945. /*
  1946.  *----------------------------------------------------------------------
  1947.  *
  1948.  * AddToDirectory --
  1949.  *
  1950.  *    Add the file descriptor to a directory.  
  1951.  *
  1952.  * Results:
  1953.  *    SUCCESS if the desciptor was added ok, FAILURE otherwise
  1954.  *
  1955.  * Side effects:
  1956.  *    The directory is modified to contain the file.
  1957.  *
  1958.  *----------------------------------------------------------------------
  1959.  */
  1960. static ReturnStatus
  1961. AddToDirectory(fid, headerPtr, writeDisk, dirIndexPtr, dirEntryPtrPtr, 
  1962.     fileNumber, fileName)
  1963.     int            fid;        /* Handle on raw disk. */
  1964.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  1965.     Boolean        writeDisk;    /* Write the disk? */
  1966.     DirIndexInfo    *dirIndexPtr;    /* Index information. */
  1967.     Fslcl_DirEntry    **dirEntryPtrPtr; /* Directory entry. */
  1968.     int             fileNumber;    /* File number to add. */
  1969.     char         *fileName;    /* Name of file to add. */
  1970. {
  1971.     int             nameLength;
  1972.     int             recordLength;
  1973.     int             leftOver;
  1974.     int            oldRecLength;
  1975.     Fslcl_DirEntry    *dirEntryPtr;
  1976.     ReturnStatus     status = SUCCESS;
  1977.  
  1978.     dirEntryPtr = *dirEntryPtrPtr;
  1979.  
  1980.     nameLength = strlen(fileName);
  1981.     recordLength = Fslcl_DirRecLength(nameLength);
  1982.  
  1983.     while (1) {
  1984.     if (dirEntryPtr->fileNumber != 0) {
  1985.         oldRecLength = Fslcl_DirRecLength(dirEntryPtr->nameLength);
  1986.         leftOver = dirEntryPtr->recordLength - oldRecLength;
  1987.         if (leftOver >= recordLength) {
  1988.         dirEntryPtr->recordLength = oldRecLength;
  1989.         dirEntryPtr = 
  1990.             (Fslcl_DirEntry *) ((int) dirEntryPtr + oldRecLength);
  1991.         dirEntryPtr->recordLength = leftOver;
  1992.         dirIndexPtr->dirOffset += oldRecLength;
  1993.         } else {
  1994.         status = NextDirEntry(fid, headerPtr, writeDisk,
  1995.                 dirIndexPtr, &dirEntryPtr);
  1996.         if (status != SUCCESS) {
  1997.             fprintf(stderr, "Can't add to directory\n");
  1998.             return status;
  1999.         }
  2000.         continue;
  2001.         }
  2002.     } else if (dirEntryPtr->recordLength < recordLength) {
  2003.         status = NextDirEntry(fid, headerPtr, writeDisk,
  2004.             dirIndexPtr, &dirEntryPtr);
  2005.         if (status != SUCCESS) {
  2006.         fprintf(stderr, "Can't add to directory\n");
  2007.         return status;
  2008.         }
  2009.         continue;
  2010.     }
  2011.     dirEntryPtr->fileNumber = fileNumber;
  2012.     dirEntryPtr->nameLength = nameLength;
  2013.     (void)strcpy(dirEntryPtr->fileName, fileName);
  2014.     leftOver = dirEntryPtr->recordLength - recordLength;
  2015.     if (leftOver > FSLCL_DIR_ENTRY_HEADER) {
  2016.         dirEntryPtr->recordLength = recordLength;
  2017.         dirEntryPtr =(Fslcl_DirEntry *) ((int) dirEntryPtr + recordLength);
  2018.         dirEntryPtr->fileNumber = 0;
  2019.         dirEntryPtr->recordLength = leftOver;
  2020.         dirIndexPtr->dirOffset += recordLength;
  2021.     } else {
  2022.         status = NextDirEntry(fid, headerPtr, writeDisk, 
  2023.                 dirIndexPtr, &dirEntryPtr);
  2024.         if (status != SUCCESS) {
  2025.         fprintf(stderr, "Can't add to directory\n");
  2026.         return status;
  2027.         }
  2028.     }
  2029.     *dirEntryPtrPtr = dirEntryPtr;
  2030.     return status;
  2031.     }
  2032. }
  2033.  
  2034. /*
  2035.  *----------------------------------------------------------------------
  2036.  *
  2037.  * OpenDir --
  2038.  *
  2039.  *    Set up the structure to allow moving through the given directory.
  2040.  *
  2041.  * Results:
  2042.  *    SUCCESS if the open was successful, FAILURE otherwise
  2043.  *
  2044.  * Side effects:
  2045.  *    The index structure is set up and *dirEntryPtrPtr set to point to
  2046.  *    the first directory entry.
  2047.  *
  2048.  *----------------------------------------------------------------------
  2049.  */
  2050. static ReturnStatus
  2051. OpenDir(fid, headerPtr, fdPtr, indexInfoPtr, dirEntryPtrPtr)
  2052.     int            fid;        /* Handle on raw disk. */
  2053.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2054.     Fsdm_FileDescriptor    *fdPtr;        /* The file descriptor for the
  2055.                      * directory. */
  2056.     DirIndexInfo     *indexInfoPtr;    /* Index info struct */
  2057.     Fslcl_DirEntry    **dirEntryPtrPtr; /* Current directory entry */
  2058. {
  2059.  
  2060.     *dirEntryPtrPtr = NULL;
  2061.     if (fdPtr->lastByte == -1) {
  2062.     /*
  2063.      * Empty directory.
  2064.      */
  2065.     return SUCCESS;
  2066.     } else if ((fdPtr->lastByte + 1) % FSLCL_DIR_BLOCK_SIZE != 0) {
  2067.     fprintf(stderr, "Directory not multiple of directory block size.\n");
  2068.     return FAILURE;
  2069.     } else if (fdPtr->fileType != FS_DIRECTORY) {
  2070.     fprintf(stderr, "OpenDir: Not a directory\n");
  2071.     return FAILURE;
  2072.     }
  2073.  
  2074.     /*
  2075.      * Initialize the index structure.
  2076.      */
  2077.     indexInfoPtr->fdPtr = fdPtr;
  2078.     indexInfoPtr->blockNum = 0;
  2079.     indexInfoPtr->blockAddr = fdPtr->direct[0] / FS_FRAGMENTS_PER_BLOCK + 
  2080.                   headerPtr->dataOffset;
  2081.     /*
  2082.      * Read in the directory block.
  2083.      */
  2084.     if (fdPtr->lastByte != FS_BLOCK_SIZE - 1) {
  2085.     fprintf(stderr, "We created a directory that's not 4K?\n");
  2086.     return FAILURE;
  2087.     }
  2088.     if (Disk_BlockRead(fid, headerPtr,
  2089.                indexInfoPtr->blockAddr,
  2090.                1, indexInfoPtr->dirBlock) < 0) {
  2091.     fprintf(stderr, "OpenDir: Read failed block %d\n",
  2092.             indexInfoPtr->blockAddr);
  2093.     return FAILURE;
  2094.     } 
  2095.     indexInfoPtr->dirOffset = 0;
  2096.     *dirEntryPtrPtr = (Fslcl_DirEntry *) indexInfoPtr->dirBlock;
  2097.     return SUCCESS;
  2098. }
  2099.  
  2100.  
  2101. /*
  2102.  *----------------------------------------------------------------------
  2103.  *
  2104.  * NextDirEntry --
  2105.  *
  2106.  *    Get a pointer to the next directory entry.
  2107.  *
  2108.  * Results:
  2109.  *    SUCCESS if the next entry was found ok, FAILURE otherwise
  2110.  *
  2111.  * Side effects:
  2112.  *    The index structure is modified and *dirEntryPtrPtr set to point
  2113.  *    to the next directory entry.
  2114.  *
  2115.  *----------------------------------------------------------------------
  2116.  */
  2117. static ReturnStatus
  2118. NextDirEntry(fid, headerPtr, writeDisk, indexInfoPtr, dirEntryPtrPtr)
  2119.     int            fid;        /* Handle on raw disk. */
  2120.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2121.     Boolean        writeDisk;    /* Write the disk? */
  2122.     DirIndexInfo     *indexInfoPtr;    /* Index information. */
  2123.     Fslcl_DirEntry    **dirEntryPtrPtr; /* Current directory entry */
  2124. {
  2125.     Fslcl_DirEntry    *dirEntryPtr;    
  2126.  
  2127.     dirEntryPtr = *dirEntryPtrPtr;
  2128.     indexInfoPtr->dirOffset += dirEntryPtr->recordLength;
  2129.     if (indexInfoPtr->dirOffset < FS_BLOCK_SIZE) {
  2130.     /*
  2131.      * The next directory entry is in the current block.
  2132.      */
  2133.     *dirEntryPtrPtr = (Fslcl_DirEntry *)
  2134.             &(indexInfoPtr->dirBlock[indexInfoPtr->dirOffset]);
  2135.     return SUCCESS;
  2136.     } else {
  2137.     Fsdm_FileDescriptor    *fdPtr;
  2138.     int            i;
  2139.  
  2140.     printf("Adding new block to directory ...\n");
  2141.  
  2142.     /*
  2143.      * Write out the current block and set up the next one.
  2144.      */
  2145.     if (writeDisk) {
  2146.         if (Disk_BlockWrite(fid, headerPtr, indexInfoPtr->blockAddr,
  2147.                 1, indexInfoPtr->dirBlock) < 0) {
  2148.         fprintf(stderr, "NextDirEntry: Write failed block %d\n",
  2149.                 indexInfoPtr->blockAddr);
  2150.         return FAILURE;
  2151.         }
  2152.     }
  2153.     fdPtr = indexInfoPtr->fdPtr;
  2154.     fdPtr->lastByte += FS_BLOCK_SIZE;
  2155.     fdPtr->numKbytes += FS_FRAGMENTS_PER_BLOCK;
  2156.     indexInfoPtr->blockNum++;
  2157.     fdPtr->direct[indexInfoPtr->blockNum] = 
  2158.                 freeBlockNum * FS_FRAGMENTS_PER_BLOCK;
  2159.     MarkDataBitmap(headerPtr, cylBitmapPtr, freeBlockNum,
  2160.                FS_FRAGMENTS_PER_BLOCK);
  2161.     indexInfoPtr->blockAddr = freeBlockNum + headerPtr->dataOffset;
  2162.     freeBlockNum++;
  2163.     for (i = 0, dirEntryPtr = (Fslcl_DirEntry *)indexInfoPtr->dirBlock; 
  2164.          i < FS_BLOCK_SIZE / FSLCL_DIR_BLOCK_SIZE;
  2165.      i++,dirEntryPtr=(Fslcl_DirEntry *)((unsigned)dirEntryPtr+FSLCL_DIR_BLOCK_SIZE)) {
  2166.         dirEntryPtr->fileNumber = 0;
  2167.         dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2168.         dirEntryPtr->nameLength = 0;
  2169.     }
  2170.     indexInfoPtr->dirOffset = 0;
  2171.     *dirEntryPtrPtr = (Fslcl_DirEntry *) indexInfoPtr->dirBlock;
  2172.     return SUCCESS;
  2173.     }
  2174. }
  2175.  
  2176.  
  2177. /*
  2178.  *----------------------------------------------------------------------
  2179.  *
  2180.  * CloseDir --
  2181.  *
  2182.  *    Flushes the current directory block to disk, if necessary.
  2183.  *
  2184.  * Results:
  2185.  *    SUCCESS if the directory was closed ok, FAILURE otherwise
  2186.  *
  2187.  * Side effects:
  2188.  *    Stuff is written to disk.
  2189.  *
  2190.  *----------------------------------------------------------------------
  2191.  */
  2192. static ReturnStatus
  2193. CloseDir(fid, headerPtr, writeDisk, indexInfoPtr)
  2194.     int            fid;        /* Handle on raw disk. */
  2195.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2196.     Boolean        writeDisk;    /* Write the disk? */
  2197.     DirIndexInfo     *indexInfoPtr;    /* Index information. */
  2198. {
  2199.  
  2200.     if (writeDisk) {
  2201.     if (Disk_BlockWrite(fid, headerPtr, indexInfoPtr->blockAddr,
  2202.                 1, indexInfoPtr->dirBlock) < 0) {
  2203.         fprintf(stderr, "CloseDir: Write (2) failed block %d\n",
  2204.                 indexInfoPtr->blockAddr);
  2205.         return FAILURE;
  2206.     }
  2207.     }
  2208.     return SUCCESS;
  2209. }
  2210.  
  2211. /*
  2212.  *----------------------------------------------------------------------
  2213.  *
  2214.  * ReadFileDesc --
  2215.  *
  2216.  *    Return the given file descriptor.
  2217.  *
  2218.  * Results:
  2219.  *    SUCCESS if file descriptor was read ok, FAILURE otherwise
  2220.  *
  2221.  * Side effects:
  2222.  *    The file descriptor struct is filled in.
  2223.  *
  2224.  *----------------------------------------------------------------------
  2225.  */
  2226. static ReturnStatus
  2227. ReadFileDesc(fid, headerPtr, fdNum, fdPtr)
  2228.     int            fid;        /* Handle on raw disk. */
  2229.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2230.     int            fdNum;        /* File number. */
  2231.     Fsdm_FileDescriptor    *fdPtr;        /* Place to store fd. */
  2232. {
  2233.     static char        block[FS_BLOCK_SIZE];
  2234.     int            blockNum;
  2235.     int            offset;
  2236.  
  2237.     blockNum = headerPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  2238.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  2239.     if (Disk_BlockRead(fid, headerPtr, blockNum, 1, 
  2240.                (Address) block) < 0) {
  2241.     fprintf(stderr, "ReadFileDesc: Read failed\n");
  2242.     return FAILURE;
  2243.     }
  2244.     bcopy((Address)&block[offset], (Address)fdPtr, sizeof(Fsdm_FileDescriptor));
  2245.     return SUCCESS;
  2246. }
  2247.  
  2248.  
  2249. /*
  2250.  *----------------------------------------------------------------------
  2251.  *
  2252.  * WriteFileDesc --
  2253.  *
  2254.  *    Write the given file descriptor.
  2255.  *
  2256.  * Results:
  2257.  *    SUCCESS if the write was successful, FAILURE otherwise
  2258.  *
  2259.  * Side effects:
  2260.  *    Stuff is written to disk.
  2261.  *
  2262.  *----------------------------------------------------------------------
  2263.  */
  2264. static ReturnStatus
  2265. WriteFileDesc(fid, headerPtr, fdNum, fdPtr)
  2266.     int            fid;        /* Handle on raw disk. */
  2267.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2268.     int            fdNum;        /* File number. */
  2269.     Fsdm_FileDescriptor    *fdPtr;        /* Place to store fd. */
  2270. {
  2271.     static char        block[FS_BLOCK_SIZE];
  2272.     int            blockNum;
  2273.     int            offset;
  2274.  
  2275.     blockNum = headerPtr->fileDescOffset + fdNum / FSDM_FILE_DESC_PER_BLOCK;
  2276.     offset = (fdNum & (FSDM_FILE_DESC_PER_BLOCK - 1)) * FSDM_MAX_FILE_DESC_SIZE;
  2277.     if (Disk_BlockRead(fid, headerPtr, blockNum, 1, 
  2278.                (Address) block) < 0) {
  2279.     fprintf(stderr, "WriteFileDesc: Read failed\n");
  2280.     return FAILURE;
  2281.     }
  2282.     bcopy((Address)fdPtr, (Address)&block[offset], sizeof(Fsdm_FileDescriptor));
  2283.     if (Disk_BlockWrite(fid, headerPtr, blockNum, 1, 
  2284.                (Address) block) < 0) {
  2285.     fprintf(stderr, "WriteFileDesc: Write failed\n");
  2286.     return FAILURE;
  2287.     }
  2288.     return SUCCESS;
  2289. }
  2290. /*
  2291.  *----------------------------------------------------------------------
  2292.  *
  2293.  * CreateDir --
  2294.  *
  2295.  *    Create a directory out of file system blocks.
  2296.  *
  2297.  * Results:
  2298.  *    None.
  2299.  *
  2300.  * Side effects:
  2301.  *    File system block set up as a directory.
  2302.  *
  2303.  *----------------------------------------------------------------------
  2304.  */
  2305. static void
  2306. CreateDir(blocks, numBlocks, dot, dotDot)
  2307.     Address    blocks;        /* Blocks to create directory in. */
  2308.     int        numBlocks;    /* Number of blocks. */
  2309.     int        dot;        /* File number of directory. */
  2310.     int        dotDot;        /* File number of parent. */
  2311. {
  2312.     Fslcl_DirEntry    *dirEntryPtr;
  2313.     char    *fileName;
  2314.     int        offset;
  2315.     int        length;
  2316.     int        i;
  2317.  
  2318.     dirEntryPtr = (Fslcl_DirEntry *)blocks;
  2319.     fileName = ".";
  2320.     length = strlen(fileName);
  2321.     dirEntryPtr->fileNumber = dot;
  2322.     dirEntryPtr->recordLength = Fslcl_DirRecLength(length);
  2323.     dirEntryPtr->nameLength = length;
  2324.     strcpy(dirEntryPtr->fileName, fileName);
  2325.     offset = dirEntryPtr->recordLength;
  2326.  
  2327.     dirEntryPtr = (Fslcl_DirEntry *)((int)blocks + offset);
  2328.     fileName = "..";
  2329.     length = strlen(fileName);
  2330.     dirEntryPtr->fileNumber = dotDot;
  2331.     dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE - offset;
  2332.     dirEntryPtr->nameLength = length;
  2333.     strcpy(dirEntryPtr->fileName, fileName);
  2334.     /*
  2335.      * Fill out the rest of the directory with empty blocks.
  2336.      */
  2337.     for (dirEntryPtr = (Fslcl_DirEntry *)&blocks[FSLCL_DIR_BLOCK_SIZE], i = 1; 
  2338.      i < (FS_BLOCK_SIZE * numBlocks) / FSLCL_DIR_BLOCK_SIZE;
  2339.      i++,dirEntryPtr=(Fslcl_DirEntry *)((int)dirEntryPtr + FSLCL_DIR_BLOCK_SIZE)) {
  2340.      dirEntryPtr->fileNumber = 0;
  2341.      dirEntryPtr->recordLength = FSLCL_DIR_BLOCK_SIZE;
  2342.      dirEntryPtr->nameLength = 0;
  2343.     }
  2344. }
  2345. int fragMasks[FS_FRAGMENTS_PER_BLOCK + 1] = {0x0, 0x08, 0x0c, 0x0e, 0x0f};
  2346.  
  2347.  
  2348. /*
  2349.  *----------------------------------------------------------------------
  2350.  *
  2351.  * MarkDataBitmap --
  2352.  *
  2353.  *    Mark the appropriate bits in the data block bitmap.
  2354.  *
  2355.  * Results:
  2356.  *    None.
  2357.  *
  2358.  * Side effects:
  2359.  *    Data block marked.
  2360.  *
  2361.  *----------------------------------------------------------------------
  2362.  */
  2363. static void
  2364. MarkDataBitmap(headerPtr, cylBitmapPtr, blockNum, numFrags)
  2365.     Ofs_DomainHeader    *headerPtr;
  2366.     unsigned char    *cylBitmapPtr;
  2367.     int            blockNum;
  2368.     int            numFrags;
  2369. {
  2370.     unsigned char    *bitmapPtr;
  2371.  
  2372.     bitmapPtr = GetBitmapPtr(headerPtr, cylBitmapPtr, blockNum);
  2373.     if ((blockNum % headerPtr->geometry.blocksPerCylinder) & 0x1) {
  2374.     *bitmapPtr |= fragMasks[numFrags];
  2375.     } else {
  2376.     *bitmapPtr |= fragMasks[numFrags] << 4;
  2377.     }
  2378. }
  2379.  
  2380. /*
  2381.  *----------------------------------------------------------------------
  2382.  *
  2383.  * ReadFileDescBitmap --
  2384.  *
  2385.  *    Read in the file descriptor bitmap.
  2386.  *
  2387.  * Results:
  2388.  *    A pointer to the file descriptor bit map.
  2389.  *
  2390.  * Side effects:
  2391.  *    Memory allocated for the bit map.
  2392.  *
  2393.  *----------------------------------------------------------------------
  2394.  */
  2395. static unsigned char *
  2396. ReadFileDescBitmap(fid, headerPtr)
  2397.     int            fid;        /* Handle on raw disk. */
  2398.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2399. {
  2400.     register unsigned char *bitmap;
  2401.  
  2402.     /*
  2403.      * Allocate the bitmap.
  2404.      */
  2405.     bitmap = (unsigned char *)malloc(
  2406.     (unsigned) headerPtr->fdBitmapBlocks * FS_BLOCK_SIZE);
  2407.     if (Disk_BlockRead(fid, headerPtr, headerPtr->fdBitmapOffset,
  2408.           headerPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  2409.     fprintf(stderr, "ReadFileDescBitmap: Read failed");
  2410.     exit(1);
  2411.     }
  2412.     return(bitmap);
  2413. }
  2414.  
  2415. /*
  2416.  *----------------------------------------------------------------------
  2417.  *
  2418.  * ReadBitmap --
  2419.  *
  2420.  *    Read the bitmap off disk.
  2421.  *
  2422.  * Results:
  2423.  *    A pointer to the bitmap.
  2424.  *
  2425.  * Side effects:
  2426.  *    Memory allocated for the bit map.
  2427.  *
  2428.  *----------------------------------------------------------------------
  2429.  */
  2430. static unsigned char *
  2431. ReadBitmap(fid, headerPtr)
  2432.     int            fid;        /* Handle on raw disk. */
  2433.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2434. {
  2435.     unsigned char *bitmap;
  2436.  
  2437.     bitmap = (unsigned char *)malloc((unsigned) 
  2438.         headerPtr->bitmapBlocks * FS_BLOCK_SIZE);
  2439.     if (Disk_BlockRead(fid, headerPtr, headerPtr->bitmapOffset,
  2440.           headerPtr->bitmapBlocks, (Address) bitmap) < 0) {
  2441.     fprintf(stderr, "ReadBitmap: Read failed");
  2442.     exit(1);
  2443.     }
  2444.     return(bitmap);
  2445. }
  2446.  
  2447. /*
  2448.  *----------------------------------------------------------------------
  2449.  *
  2450.  * WriteFileDescBitmap --
  2451.  *
  2452.  *    Write out the file descriptor bitmap.
  2453.  *
  2454.  * Results:
  2455.  *    None.
  2456.  *
  2457.  * Side effects:
  2458.  *    None.
  2459.  *
  2460.  *----------------------------------------------------------------------
  2461.  */
  2462. static void
  2463. WriteFileDescBitmap(fid, headerPtr, bitmap)
  2464.     int            fid;        /* Handle on raw disk. */
  2465.     Ofs_DomainHeader     *headerPtr;    /* Domain header. */
  2466.     unsigned char     *bitmap;    /* Bitmap to write. */
  2467. {
  2468.     if (Disk_BlockWrite(fid, headerPtr, headerPtr->fdBitmapOffset,
  2469.            headerPtr->fdBitmapBlocks, (Address)bitmap) < 0) {
  2470.     fprintf(stderr, "WriteFileDescBitmap: Write failed");
  2471.     exit(1);
  2472.     }
  2473. }
  2474.  
  2475.